2016-11-13 71 views
7

对于代码下面我理解表达的线性化Scala的可堆叠性状

全新E与d与下用乙

为E - “ç - >乙 - > 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类与表达方式混合在一起,但具有不同的打印顺序

回答

4

new E with D with C with B的第一种情况完全解释为here。它的线性化EDBC,所以当你打电话,它

  • 首先调用,
  • 然后B#foo()
  • 然后D#foo()
  • 终于E#foo()

如果您E一个特点,它最终混合:val d = new D with C with B with E,然后将仅返回"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"