Frage

Ich bin neu in Scala aus Java und verwirrt durch die Abfolge der Objektinitialisierung von Scala in einer inhärenten Hierarchie. IIRC: Wenn in Java ein Objekt der Unterklasse initialisiert wird, wird der Konstruktor seiner Basisklasse vor jedem Code seines eigenen Konstruktors aufgerufen. Während ich in der Scala bin, verhalte ich mich ganz anders. Betrachten Sie das folgende Beispiel:

class Point(val x: Int, val y: Int){
    val name = this.makeName;

    def makeName: String = {
        println("makeName at super.");

        "[" + x + ", " + y + "]";
    }

    override def toString: String = name;
}

class ColorPoint(override val x: Int, override val y: Int, var color: String) extends Point(x, y) {

    // key statement
    println(name);

    override def makeName: String = {
        println("makeName at sub.");

        super.makeName + ":" + myColor;
    }

    val myColor = color;

    override def toString: String = name;
}

Betrachten wir einfach den Bytecode des Konstruktors des ColorPoint, der mit javap ausgegeben wird. Wenn der Code die Schlüsselanweisung println(name); enthält, lautet der Bytecode

public ColorPoint(int, int, java.lang.String);
  Code:
   0:   aload_0
   1:   aload_3
   2:   putfield        #13; //Field color:Ljava/lang/String;
   5:   aload_0
   6:   iload_1
   7:   iload_2
   8:   invokespecial   #18; //Method Point."<init>":(II)V
   11:  getstatic       #24; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   14:  aload_0
   15:  invokevirtual   #28; //Method name:()Ljava/lang/String;
   18:  invokevirtual   #32; //Method scala/Predef$.println:(Ljava/lang/Object;)V
   21:  aload_0
   22:  aload_3
   23:  putfield        #34; //Field myColor:Ljava/lang/String;
   26:  return

Wir können sehen, dass das Feld myColor nach invokespecial, d. h. nach der Initialisierung der Basisklasse, initialisiert wird.

Wenn ich die Anweisung println(name); auskommentiere, lautet der Bytecode:

public ColorPoint(int, int, java.lang.String);
  Code:
   0:   aload_0
   1:   aload_3
   2:   putfield        #13; //Field color:Ljava/lang/String;
   5:   aload_0
   6:   aload_3
   7:   putfield        #15; //Field myColor:Ljava/lang/String;
   10:  aload_0
   11:  iload_1
   12:  iload_2
   13:  invokespecial   #20; //Method Point."<init>":(II)V
   16:  return

Wir sehen, dass das Feld myColor unmittelbar vor dem invokespecial initialisiert wird, d. h. bevor die Basis initialisiert wird.

Was ist dann der Grund? Jedes Dokument / Artikel spezifiziert diese Art von Verhalten?

Übrigens, Version meiner Scala ist 2.7.7final (OpenJDK Server VM, Java 1.6.0_20). Danke und beste Grüße!

War es hilfreich?

Lösung

Der Compiler führt die Dinge einfach der Reihe nach aus.Hier finden Sie einige Dokumentationen.

https://github.com/paulp/scala-faq/wiki/Initialisierungsreihenfolge

Der Hauptteil davon ist der folgende.

  1. Superklassen werden vor Unterklassen vollständig initialisiert.
  2. Andernfalls in Deklarationsreihenfolge.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top