Sequenza di inizializzazione degli oggetti in scala in una gerarchia intrinseca
Domanda
Sono nuovo di scala da java e sono confuso dalla sequenza di inizializzazione degli oggetti di scala in una gerarchia intrinseca. IIRC, in Java, se viene inizializzato un oggetto della sottoclasse, il costruttore della sua classe base viene richiamato prima di qualsiasi codice del proprio costruttore. Mentre sono in scala, ottengo un comportamento completamente diverso. Considera il seguente esempio:
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;
}
Consideriamo solo il byte code del costruttore di ColorPoint
scaricato con javap
. Se il codice include l'istruzione chiave println(name);
, il byte code è
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
Possiamo vedere che il campo myColor
viene inizializzato dopo invokespecial
, ovvero dopo l'inizializzazione della classe base.
Se commento l'istruzione println(name);
, il byte code è:
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
Vediamo che il campo myColor
viene inizializzato appena prima di invokespecial
, ovvero prima dell'inizializzazione di base.
Allora qual è il motivo? Qualche documento / articolo specifica questo tipo di comportamento?
A proposito, la versione di my scala è 2.7.7final (OpenJDK Server VM, Java 1.6.0_20). Grazie e cordiali saluti!
Soluzione
Il compilatore sta semplicemente eseguendo le cose in ordine.C'è della documentazione qui.
https://github.com/paulp/scala-faq/wiki/Ordine di inizializzazione
La parte principale è la seguente.
- Le superclassi sono completamente inizializzate prima delle sottoclassi.
- Altrimenti, in ordine di dichiarazione.