2016-11-13 24 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"