Scala可堆叠的特征

Abd*_*man 8 scala traits

对于下面的代码,因为我理解它的表达式的线性化

新的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类以与表达式相同的方式混合,但具有不同的打印顺序

lau*_*lic 6

第一个案例在这里new E with D with C with B得到了完美的解释.它的线性化是,所以当你打电话时,它EDBCd.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".