2011-04-22 74 views
2

考虑下面的代码:斯卡拉2.8:如何初始化子类

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 = [email protected] 

我怎样才能得到父类X等待s是调用时初始化a

回答

6

父项的字段和父构造函数总是初始化并在chil之前运行dren的领域和构造函数。这意味着a的呼叫发生在您的子类中设置了var s之前。

通常,从构造函数调用虚方法是一个坏主意; C++甚至不允许它(或者,而不是禁止它,当从超类的构造函数调用时,不会调用在子类中实现的方法)。

但是,如果您将var s转换为或def,您可以修改它。 lazy val在第一次访问它们的值时被初始化,不管由谁来进行; def s不存在初始化问题,如var s或val s。但是,请注意不要在a的实现中调用任何其他未初始化的结构,因为同样的问题会再次出现。

编辑:

您还可以使用Scala的“早期的定义”(或早期初始化)功能:

class Y extends { 
    var s = "Hello" 
} with X { 
    def a: Unit = println ("String is "+s) 
} 
+0

我需要's'是一个'var'因为它后来被修改在我的代码。因此,'def'和'val'都不起作用。 – Jus12 2011-04-22 13:44:57

+0

谢谢。早期定义功能很有趣。 – Jus12 2011-04-22 13:59:28

+0

你可以退后一步,多说你想做什么,而不是你想做什么? – 2011-04-22 13:59:48