我有一个抽象类,由另一个类扩展。
object StackOverflowTest extends App
{
new ChildFunction()
}
abstract class Function() {
val a: Double
val b: Double
println(a, b)
}
class ChildFunction() extends Function() {
val a = 0.02
val b = 0.2
}
当我实例化ChildFunction
时,会为0.0
和a
打印b
。
这显然不是我想要的行为,甚至是预期的行为。
我找到解决此问题的唯一方法是在ChildFunction
lazy val a = 0.02
中说明。
这是正确的解决方案吗?
答案 0 :(得分:4)
使val延迟工作,因为它移动0.02写入字段的点。要了解发生的情况,请阅读以下代码,这是scalac为您的示例生成的java字节代码。
要注意的是,字段a和b存储在子对象上,并且直到调用父对象的构造函数之后才会写入它们的值0.02和0.2。但是,在写入字段之前,将在父项的构造函数中调用println。因此你的问题。
使vals延迟工作,因为在调用a()或b()时,将调用初始化代码..这就是父类现在将在子类上调用代码来设置儿童班。
public abstract class Function implements scala.ScalaObject {
public abstract double a();
public abstract double b();
public Function(); // NB: calls a() and b() on the child class
Code:
0: aload_0
1: invokespecial #13 // Method java/lang/Object."<init>":()V
4: getstatic #19 // Field scala/Predef$.MODULE$:Lscala/Predef$;
7: new #21 // class scala/Tuple2$mcDD$sp
10: dup
11: aload_0
12: invokevirtual #25 // Method a:()D
15: aload_0
16: invokevirtual #27 // Method b:()D
19: invokespecial #30 // Method scala/Tuple2$mcDD$sp."<init>":(DD)V
22: invokevirtual #34 // Method scala/Predef$.println:(Ljava/lang/Object;)V
25: return
}
public class ChildFunction extends Function implements scala.ScalaObject {
public double a();
Code:
0: aload_0
1: getfield #12 // Field a:D
4: dreturn
public double b();
Code:
0: aload_0
1: getfield #14 // Field b:D
4: dreturn
public ChildFunction(); // NB invokes parent constructor BEFORE writing values to fields a and b.
Code:
0: aload_0
1: invokespecial #20 // Method Function."<init>":()V
4: aload_0
5: ldc2_w #21 // double 0.02d
8: putfield #12 // Field a:D
11: aload_0
12: ldc2_w #23 // double 0.2d
15: putfield #14 // Field b:D
18: return
}
你可以修复&#39;这个问题通过使用defs而不是lazy val(下面的例子)。或者更好的是,删除println并仅在完全构造ChildFunction之后调用a()和b()。
object StackOverflowTest extends App
{
new ChildFunction()
}
abstract class Function() {
def a: Double
def b: Double
println(a, b)
}
class ChildFunction() extends Function() {
override def a = 0.02
override def b = 0.2
}