Scala:父类是否可以访问仅由子级定义的方法?

标签 scala case-class self-type

我有两个从抽象基类继承的案例类。我想在抽象基类上定义一些方法,这些方法在继承的case类上使用copy方法(并因此返回子类的实例。)是否可以使用self类型来做到这一点?

示例代码:

abstract class BaseClass(a: String, b: Int) {
  this: case class => //not legal, but I'm looking for something similar

  def doubleB(newB: Int) = this.copy(b = b * 2) //doesn't work because BaseClass has no copy
}

case class HasC(a: String, b: Int, c: Boolean) extends BaseClass(a, b) {
  def doesStuffWithC(newC: Boolean) = {
    ...
  }
}

case class HasD(a: String, b: Int, D: Double) extends BaseClass(a, b) {
  def doesStuffWithD(newD: Double) = {
    ...
  }
}

由于这个问题,我已经弄清楚了如何获得想要的结果:
How to use Scala's this typing, abstract types, etc. to implement a Self type?
但是它涉及到在BaseClass中添加一个makeCopy方法,并在每个子case类中调用复制来覆盖它,并且语法(尤其是Self类型)尤其令人困惑。使用Scala的内置自动键入功能可以做到这一点吗?

最佳答案

您无法做您想做的事情,因为copy需要知道所有可能的参数。因此,即使案例类是从Copyable继承的,也不是您需要的copy。另外,如果您要保持类型的笔直,则会因Scala缺少“MyType”而受挫。因此,您不能只扩展基类。但是,您可以添加一个抽象方法并键入批注:

abstract class BaseClass[C <: BaseClass[_]](a: String, b: Int) {
  def setB(b0: Int): C
  def doubleB(b0: Int) = setB(b0*2)
}
case class HasC(a: String, b: Int, c: Boolean) extends BaseClass[HasC](a,b) {
  def setB(b0: Int) = this.copy(b = b0)
  def doesStuffWithC(c0: Boolean) = doubleB(if (c0) b else -b).copy(c = c0)
}

然后您可以:
scala> HasC("fish",1,false).doesStuffWithC(true)
res47: HasC = HasC(fish,2,true)

如果您有很多共享功能仅依赖于复制b的能力(很多方法或少数复杂方法),那么这项额外的工作将是值得的(也就是说,这解决了DRY问题)。相反,如果您想抽象HasC和其他派生类,则可以使用BaseClass[_]或添加另一个定义setB(b0: Int): BaseBase的级别,或者干脆忘记类型参数化并将BaseClass用作返回类型(但要意识到HasC无法使用BaseClass方法,并且保留其类型标识)。

关于Scala:父类是否可以访问仅由子级定义的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10304728/

相关文章:

scala - 如何使用Applicative实现并发?

scala - 使用 Scalatra 和 Casbah 进行 CRUD 操作

scala - 加特林。连接异常 : connection timed out:

scala - 与 '' this'' 没有类型/差异的显式自引用

Scala Play Framework 应用程序在更改源后无法正确重启

scala - 如何定义具有未绑定(bind)类型参数的成员的案例类?

scala - 当案例类字段是带反引号的保留 java 关键字时,spark-submit 失败

scala - 是否可以将命名参数用于 Scala 案例类匹配?

scala - Trait 继承和 self 类型注释之间的区别

Scala self 类型和collection.issue中的this.type