加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

用val重写def的Scala抛出NPE

发布时间:2020-12-16 09:58:38 所属栏目:安全 来源:网络整理
导读:我正在学习 Scala和 Scala 3rd Ed编辑,第10章,第225页,部分覆盖方法和字段,它说 The uniform access principle is just one aspect where Scala treats fields and methods more uniformly than Java. Another difference is that in Scala,fields and metho
我正在学习 Scala和 Scala 3rd Ed编辑,第10章,第225页,部分覆盖方法和字段,它说

The uniform access principle is just one aspect where Scala treats
fields and methods more uniformly than Java. Another difference is
that in Scala,fields and methods belong to the same namespace. This
makes it possible for a field to override a parameterless method. For
instance,you could change the implementation of contents in class
ArrayElement from a method to a field without having to modify the
abstract method definition of contents in class Element,as shown in
Listing 10.4:

我的代码基于这个例子

用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,模式匹配,更简单的构造(不需要新的)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读