First of all, I realize that it doesn't make much sense to override a concrete method in superclass by an abstract method in subclass. But... since in Scala it is actually possible to do this, I tried the following snippet, and the result's getting me confused.
First scenario
- The concrete method to be overridden in super-super-class
- The abstract method is in super-class
class A {
def x: String = "A"
}
abstract class B extends A {
def x: String
}
class C extends B {
def x: String = "C"
}
Executing the snippet above in scala REPL results in the follwing error:
def x: String = "C"
^
<pastie>:10: error: `override` modifier required to override concrete member:
def x: String (defined in class A)
Now the question: Why it seems that the abstract method in class B was ignored? But B.x does actually have an effect if C.x is removed from definition. Because the following snippet doesn't compile either.
class A {
def x: String = "A"
}
abstract class B extends A {
def x: String
}
class C extends B
results in the following error
class C extends B
^
<pastie>:9: error: class C needs to be abstract. No implementation found in a subclass for deferred declaration
def x: String (defined in class B)
Second scenario
- The concrete method to be overridden in super-class
- The abstract method is in trait
class A {
def x: String = "A"
}
trait B {
def x: String
}
class C extends A with B
Try instantiate C,
scala> (new C).x
val res0: String = A
It looks like the B.x abstract method just got ignored by compiler.
Update
In the first edition of my question, I idiotically forgot to extends A in the second scenario, which leads to an incorrect conclusion that class and trait behave differently in my examples. I sincerely apologize for my negligence.
Let me try to rephase my question:
In both the first and second scenario, what is the effect of the abstract B.x in the middle of class hierarchy?
As I understand it, by inheritance and method resolution order (MRO),
- in the first scenario
B.xoverridesA.xandC.xoverridesB.x. SinceB.xis abstract, whenC.ximplementsB.x, it need not specifyoverridemodifier. - in the second scenario,
B.xoverridesA.xandCdidn't implement the abstractB.x. SoCshould be abstract and does not compile.
But it seems to me that the compiler just ignored the abstract method B.x in the middle of class hierarchy. Is this behavior defined somewhere in the language specification, or this is totally unintended and unexpected (and just a compiler bug)?