问题描述
我尝试在特征中使用抽象的 val
来初始化另一个值.我得到了一个 NullPointerException
.我将行为归结为一个最小的测试用例:
I tried using an abstract val
in a trait to initialize another value. I got a NullPointerException
. I boiled the behaviour down to a minimal test case:
trait MessagePrinter {
val message: String
println(message)
}
class HelloPrinter extends MessagePrinter {
val message = "Hello World"
}
val obj = new HelloPrinter()
println(obj.message)
这个小程序产生以下结果:
This little program yields the following result:
null
Hello World
我的印象是 val 可能永远不会改变.这是预期的行为还是编译器错误?如何解决此问题并在初始化期间打印 Hello World
?
I was under the impression that a val may never change. Is this expected behaviour or is it a compiler bug? How can I work around this issue and print Hello World
during initialization?
推荐答案
根据 Scala 规范的第 5.1 节,超类首先被初始化.尽管 vals
通常无法重新实例化,但它们在构造期间确实以默认初始值开始.您可以使用具有不同语义的 def
:
By section 5.1 of the Scala specification, super classes are initialized first. Even though vals
cannot normally be reinstantiated, they do start with a default initial value during construction. You can either use def
, which has different semantics:
trait MessagePrinter {
def message: String
println(message)
}
class HelloPrinter extends MessagePrinter {
def message = "Hello World"
}
或者你可以考虑像这样切换:
Or you might consider switching things around like so:
class HelloPrinter extends { val message = "Hello World" } with MessagePrinter
在这种情况下,超类按顺序计算,以便 MessagePrinter
初始化应按需要工作.
In which case the super classes are evaluated in order, so that the MessagePrinter
initialization should work as desired.
这篇关于如何在 subtrait 中初始化 trait 的 vals?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!