用val重写def的Scala抛出NPE
我正在学习
Scala和
Scala 3rd Ed编辑,第10章,第225页,部分覆盖方法和字段,它说
我的代码基于这个例子 用def abstract class Element { def contents: Array[String] val height = contents.length val width = if (height == 0) 0 else contents(0).length } class ArrayElement(contnts: Array[String]) extends Element { def contents: Array[String] = contnts } // -- val ae = new ArrayElement(Array("hello","world")) ae.height ae.width 我明白了 ae: ArrayElement = ArrayElement@7cd3ba8e res0: Int = 2 res1: Int = 5 将def覆盖为ArrayElement中的val abstract class Element { def contents: Array[String] val height = contents.length val width = if (height == 0) 0 else contents(0).length } class ArrayElement(contnts: Array[String]) extends Element { val contents: Array[String] = contnts } // -- val ae = new ArrayElement(Array("hello","world")) ae.height ae.width 我得到了NPE java.lang.NullPointerException at #worksheet#.Element.<init>(scratch.scala:4) at #worksheet#.ArrayElement.<init>(scratch.scala:10) at #worksheet#.ae$lzycompute(scratch.scala:15) at #worksheet#.ae(scratch.scala:15) at #worksheet#.#worksheet#(scratch.scala:14) 我错过了什么? 解决方法
类级别字段在其他任何内容之前初始化,这意味着分配了null.你可以使声明成为一个惰性val,并且在调用它之前不会初始化它.这就是def工作的原因.但是更好的方法是,不要创建隐藏私有构造函数字段的类公共字段,而是将构造函数字段设置为public,如下所示:
class ArrayElement(val contnts: Array[String]) extends Element {} 由于这里也有一个家长班,所以最好将它标记为重写; class ArrayElement(override val contnts: Array[String]) extends Element {} 如果这将是一个无状态数据容器类,最好的选择是使它成为一个案例类,其中(在其他几个方面)具有默认的公共字段. case class ArrayElement(override val contnts: Array[String]) extends Element 这是更惯用的scala,它将为您提供基于值的equals,hashCode,模式匹配,更简单的构造(不需要新的) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |