séquence d'initialisation de l'objet en rampe dans une hiérarchie inhérente
Question
Je suis nouveau à rampe de Java et confus par la séquence d'initialisation d'objet de rampe dans une hiérarchie inhérente. IIRC, en Java, si un objet de sous-classe est initialisé, constructeur de sa classe de base est appelée avant tout code de son propre constructeur. Alors que dans scala, je reçois un comportement totalement différent. Prenons l'exemple suivant:
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;
}
Soit le code de considérer seulement l'octet du constructeur de ColorPoint
jeté avec javap
. Si le code inclut la déclaration clé println(name);
le code octet est
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
Nous pouvons voir myColor
de champ est initialisé après invokespecial
, à savoir après l'initialisation de la classe de base.
Si je commente la déclaration println(name);
le code octet est:
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
Nous voyons que myColor
de champ est initialisé juste avant invokespecial
, à savoir avant de base est initialisé.
Alors quelle est la raison? Tout document / article précise ce genre de comportement?
BTW, la version de mon scala est 2.7.7final (OpenJDK serveur VM Java 1.6.0_20). Merci et meilleures salutations!
La solution
Le compilateur exécute simplement les choses dans l'ordre. Il y a une documentation ici.
https://github.com/paulp/scala-faq/wiki/ initialisation-ordre
La partie principale de c'est le suivant.
- Superclasses sont complètement initialisé avant les sous-classes.
- Dans le cas contraire, dans l'ordre de déclaration.