Последовательность инициализации объекта в scala во внутренней иерархии
Я новичок в scala из java и смущен последовательностью инициализации объекта scala во внутренней иерархии. IIRC, в Java, если объект подкласса инициализирован, конструктор его базового класса вызывается перед любым кодом его собственного конструктора. Находясь в скале, у меня совершенно другое поведение. Рассмотрим следующий пример:
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;
}
Давайте просто рассмотрим байт-код конструктора ColorPoint
сбрасывается с javap
, Если код включает ключевое заявление println(name);
байт-код
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
Мы можем увидеть поле myColor
инициализируется после invokespecial
после инициализации базового класса.
Если я закомментирую заявление println(name);
Байт-код:
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
Мы видим это поле myColor
инициализируется непосредственно перед invokespecial
перед инициализацией базы.
Тогда в чем причина? Какой-нибудь документ / статья определяет такое поведение?
Кстати, версия моего scala - 2.7.7финал (OpenJDK Server VM, Java 1.6.0_20). Спасибо и всего наилучшего!
1 ответ
Компилятор просто выполняет все по порядку. Здесь есть некоторая документация.
https://github.com/paulp/scala-faq/wiki/Initialization-Order
Основная часть из этого заключается в следующем.
- Суперклассы полностью инициализируются перед подклассами.
- В противном случае в порядке декларирования.