Scala stackable traits
For the code below as I understand it linearization of expression
new E with D with C with B
is E -> C -> B -> D. So then shouldnt the expression d.foo() in the code
below evaluate to ECBD instead of CBDE. What am I missing?
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
I have noticed that if I have a class F like below
class F extends A with D with C with B{
override def foo() = "F" + super.foo()
}
and do
new F().foo
it prints "FCBD"
It seems a bit inconsistent to me because class F is mixed in the same way as the expression but has a different print order
The first case with new E with D with C with B
is perfectly explained here. Its linearization is EDBC
, so when you call d.foo()
, it
C#foo()
, B#foo()
, D#foo()
E#foo()
. If you make E
a trait and mix it in the end: val d = new D with C with B with E
, then d.foo()
will return just "E"
, because trait E
is the "last" in the linearization and just overrides foo
.
The case of F
is different, because you define foo
as "F" + super.foo()
, and super
in this case is A with D with C with B
whose linearization is ADBC
, so new F().foo()
- first prints "F"
, - then its super.foo()
which is "CBD"
.
By the way, try changing A#foo()
to return "A"
, then you will see that in E
you override A's foo
so "A"
doesn't appear in the result, and in F
it is "FCBDA"
.
上一篇: 如何使用带有EventBus的呼叫类型
下一篇: 斯卡拉可堆叠的特征