对于下面的代码,因为我理解它的表达式的线性化
新的E与D与C与B
是E - > C - > B - > D.那么在代码中不应该使用表达式d.foo()
下面评估ECBD而不是CBDE.我错过了什么?
trait A {
def foo(): String = ""
}
trait B extends A {
abstract override def foo() = "B" + super.foo()
}
trait C extends B {
abstract override def foo() = "C" + super.foo()
}
trait D extends A {
abstract override def foo() = "D" + super.foo()
}
class E extends A{
override def foo() = "E"
}
var d = new E with D with C with B;
d.foo() //prints CBDE
Run Code Online (Sandbox Code Playgroud)
我注意到如果我有一个类F如下
class F extends A with D with C with B{
override def foo() = "F" + super.foo()
}
Run Code Online (Sandbox Code Playgroud)
并做
new F().foo
Run Code Online (Sandbox Code Playgroud)
它打印"FCBD"
这对我来说似乎有点不一致,因为F类以与表达式相同的方式混合,但具有不同的打印顺序
第一个案例在这里new E with D with C with B
得到了完美的解释.它的线性化是,所以当你打电话时,它EDBC
d.foo()
C#foo()
,B#foo()
,D#foo()
E#foo()
.如果你做E
了一个特性并在最后混合它:val d = new D with C with B with E
那么d.foo()
将只返回"E"
,因为特征E
是线性化中的"最后"并且只是覆盖foo
.
情况F
是不同的,因为你定义foo
为"F" + super.foo()
,super
在这种情况下是A with D with C with B
线性化ADBC
,所以new F().foo()
- 首先打印"F"
, - 然后它super.foo()
是"CBD"
.
顺便说一句,尝试改变A#foo()
返回"A"
,然后你会看到E
你重写A的foo
所以"A"
不会出现在结果中,而在F
它中"FCBDA"
.