不确定这是否是正确的解决方案,但如果您的trait B
extends A
(和 override b
),那么一切编译正常:
首先让我们定义A
并AA
喜欢您在问题中提出它们:
C:\Users\VonC>scala
Welcome to Scala version 2.8.0.RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class A {
| def b { println("A b") }
| }
defined class A
scala> new A
res5: A = A@153bedc4
scala> res5.b
A b
scala> abstract class AA extends A {
| override def b
| }
defined class AA
你做了什么:
scala> trait B {
| override def b { println("B b") }
| }
<console>:6: error: method b overrides nothing
override def b { println("B b") }
^
我对特征 B 的尝试(为了能够添加“ override
”):
scala> trait B extends A {
| override def b { println("B b") }
| }
defined trait B
所以现在:
scala> class C extends AA with B {}
defined class C
scala> new C
res7: C = C@1497b7b1
scala> res7.b
B b
调用正确的b
覆盖方法C.b
至于您明显的“不一致”,请参阅Scala for Java Refugees Part 5: Traits and Types:
首先,有一个令人讨厌的override
关键字。我在关于基本 OOP 的文章中提到过,任何覆盖超类中的方法的方法都必须使用 override 修饰符声明。当时,我把它比作强制使用@Override
注释的语言,其主要目的是强制执行良好的实践。
trait 强大的真正关键在于编译器在继承类中处理它们的方式。
Traits 实际上是 mixins,而不是真正的父类。
任何非抽象特征成员实际上都包含在继承类中,就像类的物理部分一样。好吧,不是身体上的,但你明白了。
就好像编译器对非抽象成员执行剪切和粘贴并将它们插入到继承类中一样。这意味着继承路径没有歧义,这意味着没有钻石问题。
所以在你的第二个例子中不需要override
关键字。