Kel*_*nis 5 scala self-type case-class
我有两个从抽象基类继承的case类.我想在抽象基类上定义一些方法,这些方法在继承case类上使用复制方法(因此返回子类的实例.)有没有办法使用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) = {
...
}
}
Run Code Online (Sandbox Code Playgroud)
由于这个问题,我已经想出如何得到我想要的结果: 如何使用Scala的这种类型,抽象类型等来实现Self类型? 但它涉及向BaseClass添加一个makeCopy方法,并通过在每个子案例类中调用复制来覆盖它,并且语法(特别是对于Self类型)相当混乱.有没有办法用Scala的内置自键型来做到这一点?
你不能做你想做的事,因为copy 需要知道所有可能的参数.因此,即使继承了案例类Copyable,也不是copy您需要的.此外,如果你要保持这些类型,你会被斯卡拉缺乏"挫败"所挫败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)
}
Run Code Online (Sandbox Code Playgroud)
然后你可以:
scala> HasC("fish",1,false).doesStuffWithC(true)
res47: HasC = HasC(fish,2,true)
Run Code Online (Sandbox Code Playgroud)
如果你有很多共享功能取决于复制的能力b(很多方法,或者很少的复杂方法),这个额外的工作将是值得的- 也就是说,这解决了DRY问题.如果你想要抽象HasC和其他派生类,你可以使用BaseClass[_]或添加另一个定义setB(b0: Int): BaseBase或者只是忘记类型参数化的级别并将其BaseClass用作返回类型(但是认识到它HasC不能使用BaseClass方法并且仍然保留其类型标识).