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

  • first calls C#foo() ,
  • then B#foo() ,
  • then D#foo()
  • and finally 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" .

    链接地址: http://www.djcxy.com/p/94004.html

    上一篇: 如何使用带有EventBus的呼叫类型

    下一篇: 斯卡拉可堆叠的特征