固有层次结构中scala中的对象初始化序列
题
我是java中的scala新手,并被固有层次结构中scala的对象初始化序列所困惑。IIRC,在Java中,如果子类的对象被初始化,则在其自己的构造函数的任何代码之前调用其基类的构造函数。在scala中,我得到了完全不同的行为。考虑以下示例:
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
, ,即base初始化之前。
那原因是什么?任何文档/文章指定这种行为?
顺便说一句,我的scala版本是2.7.7final(OpenJDK Server VM,Java1.6.0_20)。谢谢,并致以最良好的问候!
解决方案
编译器只是按顺序执行事物。这里有一些文档。
https://github.com/paulp/scala-faq/wiki/Initialization-Order
从它的主要部分如下。
- 超类在子类之前完全初始化。
- 否则,按声明顺序。
不隶属于 StackOverflow