In Scala, can I override a concrete field containing a list and append something to it in the subclass?
Here's a simplification of the classes I have:
trait RequiredThings {
val requiredThings: Seq[String]
}
class SimpleCalculator with RequiredThings {
val requiredThings = List("a", "b")
}
class ComplicatedCalculator extends SimpleCalculator with RequiredThings {
self: SimpleCalculator =>
override val requiredThings:List[String] = List("c") ::: self.requiredThings
}
In this version, I'm using a self-type annotation, but I'm not completely positive that's the way to go. I think I could probably get it to work by conver开发者_开发问答ting requiredThings
to a method throughout, but I'd like to try it as a field.
Final solution:
trait RequiredThings {
def requiredThings: Seq[String]
}
class SimpleCalculator with RequiredThings {
def requiredThings = List("a", "b")
}
class ComplicatedCalculator extends SimpleCalculator with RequiredThings {
override def requiredThings:List[String] = List("c") ::: super.requiredThings
}
Yes, super calls to methods "inherited" through the self-type are not yet implemented. This will change (somewhat) soon. In the meantime, you should use inheritance instead.
Funny enough, I stepped on the same issue yesterday.
The way self types are implemented currently, if you override a method (or value) there's no way to refer to the overridden method.
The following will loop:
class A { def foo = "a" }
trait B { self: A => override def foo = self.foo + "b" }
(note: you cannot call super.foo
, the parent of B
is ScalaObject
, not A
)
I also tried with one more indirection, but the program still loops.
class A { def foo = "a"; def fooA = A.this.foo }
trait B { this: A => override def foo = fooA + "b" }
There is work going on currently on self types, maybe this will change.
It makes sense to have requiredThings
as a def
at least in the trait
- this will give you more flexibility
精彩评论