NPE in using scala Array.fill



我正在阅读Lex Spoon的Programming in Scala,第三版(也出现在第四版中);比尔·文纳斯;马丁·奥德斯基,并在此过程中尝试示例。

本书中的以下示例 |在斯卡拉小提琴中运行

abstract class Element {
def contents: Array[String]
val height = contents.length
val width = if (height == 0) 0 else contents(0).length
}
class UniformElement(
ch: Char,
override val width: Int,
override val height: Int
) extends Element {
private val line = ch.toString * width
def contents = Array.fill(height)(line)
}
val e: Element = new UniformElement('x', 2, 3)

给出java.lang.NullPointerException,当在REPL或Eclipse工作表中尝试时。

如果我改变

private val line = ch.toString * width

private def line = ch.toString * width

不会发生任何错误。

有人可以解释一下吗?

我正在使用 scala 2.11.8

这里的问题是,当您定义contents时,line时,构造函数中仍未定义。如果 line 是一个val,它不会选择被覆盖的width,而是使用抽象的,而抽象的contents仍然没有定义,你得到 NPE。您可以通过查看堆栈跟踪并注意 NPE 是由抽象类中的width定义引发

的。当line被定义为方法时,它不会执行,直到你调用它,到那时内容将被完全定义,因为它可以调用将完全定义的line(另一个方法)。

在 ScalaFiddle 上运行

abstract class Element {
def contents: Array[String]
val height = contents.length
val width = if (height == 0) 0 else contents(0).length
}
class UniformElement(
ch: Char,
override val width: Int,
override val height: Int
) extends Element {
private def line: String = ch.toString * width
def contents = Array.fill(height)(line)
}
val e3: Element = new UniformElement('x', 2, 3)

底线:你在linecontents之间有一种">循环依赖"。

最新更新