Reputation: 2045
Assuming I have a simple abstract base class like so:
abstract class MyAbstractBaseClass {
def hello : Unit
}
and then I write a "stacking" trait like so:
trait MyTrait extends MyAbstractBaseClass {
abstract override def hello : Unit =
{
super.hello
println("How are you?");
}
}
then why won't Scala let me define a subclass as follows:
class MyClass extends MyAbstractBaseClass with MyTrait {
override def hello : Unit = println("Hello!")
}
error: overriding method hello in trait MyTrait of type => Unit;
method hello needs `abstract override' modifiers
If I try their suggestion of using 'abstract override':
class MyClass extends MyAbstractBaseClass with MyTrait {
abstract override def hello : Unit = println("Hello!")
}
error: `abstract override' modifier only allowed for members of traits
Can anyone help me understand this?
P.S. I know that the below does work:
class MyClass extends MyAbstractBaseClass {
override def hello : Unit = println("Hello!")
}
val x = new MyClass with MyTrait
x.hello
Hello!
How are you?
but am trying to understand why the former does not.
In summary: why can't I provide an implementation of the abstract base class - while also taking advantage of the trait's functionality?
Upvotes: 1
Views: 1388
Reputation: 22171
The trick is that you can't have an "abstract" method in the flow of the linearization, that is called from a super
call.
Try this, you will see it compiles:
abstract class MyAbstractBaseClass {
def hello : Unit
}
class SubClass extends MyAbstractBaseClass {
def hello {
println("toto")
}
}
trait MyTrait extends MyAbstractBaseClass {
abstract override def hello : Unit =
{
super.hello
println("How are you?")
}
}
class MyClass extends SubClass with MyTrait { //note the CONCRETE SubClass here
override def hello : Unit = println("Hello!")
}
new MyClass().hello
You got the error, because the compiler starts with MyTrait
(at the top of the stack, so the first to be called) and that MyTrait
calls through super
an abstract method... (of MyAbstractBaseClass
) => it crashes since your super
call can't target immediately a concrete method.
In my code snippet, you will notice that MyTrait
is "at the top" (during linearization) of a concrete Subclass
class, that makes the trick.
Upvotes: 2