Scala Initialisierungsverhalten
-
26-09-2019 - |
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.
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