请考虑以下代码:
abstract class X {
def a:Unit
a
}
class Y extends X {
var s:String = "Hello"
def a:Unit = println ("String is "+s)
}
这给出了以下输出:
scala> new Y
String is null
res6: Y = Y@18aeabe
如何在调用X
s
等待a
初始化
答案 0 :(得分:6)
父项的字段和父构造函数始终初始化并在子项的字段和构造函数之前运行。这意味着对a
的调用发生在子类中设置var s
之前。
通常,从构造函数调用虚方法是个坏主意; C ++甚至不允许它(或者,而不是禁止它,在从超类的构造函数调用时不调用子类中实现的方法)。
但是,如果您将var s
中的class Y
转换为lazy val
或def
,则可以解决此问题。 lazy val
在第一次访问其值时被初始化,无论是谁; def
不存在var
或val
等初始化问题。但是,请注意不要在a
的实现中调用任何其他未初始化的结构,因为同样的问题将再次出现。
修改强>
您还可以使用Scala的“早期定义”(或早期初始化)功能:
class Y extends {
var s = "Hello"
} with X {
def a: Unit = println ("String is "+s)
}