gpt4 book ai didi

Scala 用 val 覆盖 def 抛出 NPE

转载 作者:行者123 更新时间:2023-12-04 14:25:12 26 4
gpt4 key购买 nike

我在学习ScalaProgramming in Scala 3rd Ed , Ch 10, Page 225 , 部分 Overriding methods and fields , 它说

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:



我基于示例的代码是

与定义
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

ArrayElement 中的 def 被覆盖为 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被安排了。您可以将声明设为 lazy val并且在调用它之前不会被初始化。这就是 def 起作用的原因。不过,一个更好的方法不是创建一个隐藏私有(private)构造函数字段的类公共(public)字段,而是像这样使构造函数字段公开:

class ArrayElement(val contnts: Array[String]) extends Element {}

由于这里也有一个父类,最好将其标记为覆盖;
class ArrayElement(override val contnts: Array[String]) extends Element {}

如果这将是一个无状态数据容器类,最好的选择是使其成为 case class ,其中(除其他几项外)具有默认公共(public)字段。
case class ArrayElement(override val contnts: Array[String]) extends Element

这是更惯用的scala,它将为您提供基于值(value)的 equals , hashCode ,模式匹配,构造更简单(无需 new)

关于Scala 用 val 覆盖 def 抛出 NPE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37485464/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com