Scala 2.8:如何初始化子类 [英] Scala 2.8: how to initialize child class
问题描述
考虑以下代码:
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
在调用a
推荐答案
父字段和父构造函数总是在子字段和构造函数之前初始化和运行.这意味着对 a
的调用发生在您的 var s
在子类中设置之前.
The parent's fields and the parent constructor are always initialized and run before the children's field and constructor. It means that the call to a
happens before your var s
is set in the child class.
一般来说,从构造函数调用虚方法是个坏主意;C++ 甚至不允许它(或者,而不是不允许它,当从超类的构造函数调用时,不调用子类中实现的方法).
In general, it's a bad idea to call a virtual method from a constructor; C++ even disallows it (or, rather than disallowing it, doesn't call the method implemented in the child class when called from the superclass's constructor).
但是,如果将 class Y
中的 var s
转换为 lazy val
或 def<,则可以修复它/code> 代替.
lazy val
s 在第一次访问它们的值时被初始化,无论是谁;def
s 没有像 var
s 或 val
s 这样的初始化问题.但是,请注意不要从 a
的实现中调用任何其他未初始化的结构,因为同样的问题会再次出现.
However, you can fix it if you turn your var s
in class Y
into a lazy val
or a def
instead. lazy val
s are initialized the first time their value is accessed, no matter by whom; def
s pose no initialization issues like var
s or val
s. However, be careful not to call any other uninitialized structure from within the implementation of a
, as the same problem will show up again.
您还可以使用 Scala 的早期定义"(或早期初始化)功能:
You can also use Scala's "early definitions" (or early initialization) feature:
class Y extends {
var s = "Hello"
} with X {
def a: Unit = println ("String is "+s)
}
这篇关于Scala 2.8:如何初始化子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!