Frage

Schauen Sie bitte auf den folgenden Code.

trait MyTrait { val myVal : String }

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

class MyClass2(val myVal: String) extends MyTrait 

Warum wird die Initialisierung unterscheiden, um im Fall von MyClass und MyClass2? Der Konstruktor von MyClass wird als

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

Der Konstruktor von MyClass2 wird

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

Ich denke, die Initialisierung sein sollte, als MyClass2 Konstruktor tut, die für beide Fälle gleich.

War es hilfreich?

Lösung

Am Ende des Abschnitts 5.1 der Scala Spezifikation , die folgendes definiert:

  

Vorlage Auswertung. eine Vorlage Betrachten sc mit mt 1 mit mt   n {Statistiken} . Ist dies die Vorlage von   ein Merkmal (§5.3.3) dann ihre   mixin-Evaluierung besteht aus einem eval-   uation der Anweisungsfolge   Statistiken. Ist dies nicht eine Vorlage eines   trait, dann seine Auswertung besteht aus   die folgenden Schritte aus.

     
      
  • Zuerst wird der Oberklassenkonstruktors sc ausgewertet (§5.1.1).
  •   
  • Dann werden alle Basisklassen in der Vorlage Linearisierung (§5.1.2) nach oben   auf die übergeordnete Klasse der Vorlage bezeichnet   von sc sind mixin bewertet.   Mixin-Auswertung Geschieht in umgekehrter   Reihenfolge des Auftretens in der   Linearisierung.
  •   
  • Schließlich werden die Anweisungsfolge Statistiken ausgewertet wird.
  •   

Beachten Sie jedoch, dass die Konstruktorparameter können durch jedes Konstrukteuren verwendet werden, die ihm folgen. Daher muss es ihnen vor initialisiert werden. Dies wird explizit am Ende des Abschnitts 5.1.1:

  

Eine Auswertung eines Konstruktor   Aufruf x.c Targs. .   . (Argsn) besteht aus folgenden   Schritte:

     
      
  • Zuerst wird das Präfix x ausgewertet wird.
  •   
  • Dann werden die Argumente args1. . . , Argsn von links ausgewertet   rechts.
  •   
  • Schließlich wird die Klasse konstruiert wird durch Auswertung der initialisierte   Vorlage der Klasse bezeichnet durch    c .
  •   

Das Sie haben kein Problem mit, aber Sie haben ein Problem mit {Statistiken} zuletzt wird ausgeführt. Der Grund, warum {Statistiken} wird zuletzt ausgeführt ist, dass es Attribute seiner Vorfahren Klassen und Eigenschaften verweisen kann, während die Vorfahren offensichtlich keine Kenntnis über seine Nachkommen haben. Daher müssen die Vorfahren vollständig vor initialisiert werden {Statistiken} ausgeführt wird.

Natürlich ist es möglich, dass Sie tun frühe Initialisierung benötigen. Dies wird durch Abschnitt behandelt 5.1.6: Früh Definitionen. Hier ist, wie Sie es schreiben würde:

class MyClass extends { val myVal = "Value" } with MyTrait
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top