斯卡拉可堆叠的特征

对于下面的代码,据我所知,表达式的线性化

新的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

我注意到,如果我有像下面这样的F类

class F extends A with D with C with B{
      override def foo() = "F" + super.foo()
}

并做

new F().foo

它打印“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是线性化中的“last”,并且只是忽略了foo

    F的情况是不同的,因为你将foo定义为"F" + super.foo() ,在这种情况下, superA with D with C with B的线性化是ADBC ,所以new F().foo()首先打印"F" ,然后是它的"CBD" super.foo()

    顺便说一句,尝试改变A#foo()返回"A" ,然后你会看到在E你重写了A的foo所以"A"不会出现在结果中,而在F它是"FCBDA"

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

    上一篇: Scala stackable traits

    下一篇: join with empty suffix