2016-11-13 11 views
7

przypadku poniżej kodu, kiedy to rozumieć linearyzacji ekspresjiScala wieżowych cechy

nowy E o o D C B

jest E -> C -> B -> D. Tak więc nie powinni wyrażenie d.foo() w kodzie

poniżej oceniany jako ECBD zamiast CBDE. czego mi brakuje?

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 

Zauważyłem, że jeśli mam klasy F jak poniżej

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

i zrobić

new F().foo 

drukuje "FCBD"

Wydaje się nieco niespójne mnie, ponieważ klasa F jest mieszana w taki sam sposób jak wyrażenie, ale ma inne zamówienie drukowania

Odpowiedz

4

Pierwszy przypadek z new E with D with C with B jest doskonale wyjaśniony here. Jego linearyzacja jest EDBC, więc podczas rozmowy , to

  • pierwsze zaproszenia ,
  • następnie B#foo(),
  • następnie D#foo()
  • i wreszcie E#foo().

Jeśli się E cecha i wymieszać ją w końcu: val d = new D with C with B with E, następnie powróci tylko "E", ponieważ cecha E jest „ostatni” w linearyzacji i po prostu nadpisuje foo.

Przypadek F jest inny, ponieważ można zdefiniować foo jak "F" + super.foo() i super w tym przypadku jest A with D with C with B którego linearyzacja jest ADBC, więc new F().foo() - pierwsze odbitki "F", - wtedy jego super.foo() co jest "CBD".

Przy okazji, spróbuj zmienić A#foo() wrócić "A", to widać, że w E zastąpić tak "A" nie wydaje się być na foo w wyniku, aw F to "FCBDA".