本文介绍了如何在 subtrait 中初始化 trait 的 vals?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在特征中使用抽象的 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 08:10