2010-09-30 12 views
15

Proszę spojrzeć na poniższy kod.Działanie inicjujące Scala

trait MyTrait { val myVal : String } 

class MyClass extends MyTrait { val myVal = "Value" } 

class MyClass2(val myVal: String) extends MyTrait 

Dlaczego kolejność inicjalizacji różnią się w przypadku MyClass i MyClass2? Konstruktor MyClass będzie tak

MyClass() { 
    MyTrait$class.$init$(this); 
    myVal = value 
} 

Konstruktor MyClass2 będzie

MyClass2(String myVal) { this.myVal = myVal; MyTrait$class.$init$(this) } 

myślę kolejność inicjalizacji powinien być jak konstruktor MyClass2 „s robi, taka sama dla obu przypadków.

Odpowiedz

23

Na końcu sekcji 5.1 Scala specification następujące zostało określone

szablon oceny. Rozważmy szablon sc z mt 1 z mt n {stats}. Jeśli jest to szablon z cechą (§5.3.3), to jego ocena składa się z eval- 8 statystyk sekwencji instrukcji . Jeśli nie jest to szablon cechy , jego ocena składa się z następujących kroków: .

  • Najpierw oceniany jest konstruktor superklasy sc (§5.1.1).
  • Następnie wszystkie klasy bazowe w linearyzacji szablonu (§5.1.2) w górę do superklasy szablonu oznaczonej przez sc są oceniane przez mixin. Awaria pomiaru miksu w odwrotnej kolejności kolejność występowania w linearyzacji .
  • Ostatecznie oceniane są statystyki sekwencji instrukcji.

Należy jednak zauważyć, że parametry konstruktora mogą być używane przez dowolne konstruktory, które go śledzą. Dlatego musi zostać zainicjowany przed nimi. Jest to wyraźnie na końcu sekcji 5.1.1:

Ocenę konstruktora inwokacja x.c targs. . . (argsn) składa się z następujących etapów :

  • najpierw przedrostek x ocenia.
  • Następnie argumenty: args1,. . . , argsn są oceniane od lewej do prawej.
  • Na koniec konstruowana klasa jest inicjalizowana przez sprawdzenie szablonu klasy określonej przez c.

to, że nie ma żadnego problemu z, ale masz problem z {} statystykach jest wykonywany jako ostatni. Powód, dla którego {stats} jest wykonywany jako ostatni, polega na tym, że może on odnosić się do atrybutów jego klas przodków i cech, podczas gdy przodkowie oczywiście nie mają wiedzy o swoich potomkach. W związku z tym przodkowie muszą zostać w pełni zainicjowani przed wykonaniem {stats}.

Oczywiście możliwe jest, że do potrzebują wczesnego inicjowania. Jest to omówione w sekcji 5.1.6: Wczesne definicje. Oto, jak go napisać:

+0

W końcu widziałem powód, dla którego Scala inicjuje obiekt w tej kolejności. Dzięki za odpowiedź, Daniel. – Dmitry