我有一个扩展抽象类的case类。在其主构造函数中,超类引用在子类中定义的抽象值。
abstract class SuperClass {
def abstractValue: Seq[Int]
val concreteValue: Int = {
abstractValue.head
}
}
case class SubClass() extends SuperClass {
override val abstractValue: Seq[Int] = Seq(1,2,3)
}
我期望创建SubClass
的实例会导致对象abstractValue = Seq(1,2,3)
和concreteValue = 1
。但是,创建SubClass
的实例会引发NullPointerException
,因为Scala会尝试在concreteValue
之前初始化abstractValue
,这意味着后者在null
时为abstractValue
已初始化。
如何使这项工作?我试过的一些事情:
SubClass
中val
的声明从def
更改为abstractValue
可以解决问题,但这会导致abstractValue
被重新初始化的意外后果每次引用它。这可能在示例中没问题,但在以下情况下不是这样:
abstractValue
的初始化很昂贵。concreteValue
的初始化不可重复(我的用例)。SuperClass
中val
的声明从def
更改为abstractValue
同样如此。SuperClass
中def
的声明从val
更改为var
并不能解决问题。val
代替abstractValue
来解决这个问题,但我喜欢我的案例类实例不可变,非常感谢。答案 0 :(得分:2)
我发现满足问题中提到的所有限制的唯一解决方案是将override lazy val abstractValue: Seq[Int] = Seq(1,2,3)
的初始化更改为惰性:
abstractValue
这违反直觉导致concreteValue
的初始化早于发生。具体来说,它发生在“需要时”,即concreteValue
初始化期间。
abstractValue
定义为懒惰(而不是Document doc = null;
try {
doc = Jsoup.connect("http://en.wikipedia.org/").get();
} catch (IOException e) {
e.printStackTrace();
}
)也解决了这个问题。这种方法更直观,更易于维护。