我正在学习Scala
和在Scala第3版编程
,第10章,第225页
,部分覆盖方法和字段
,它说
统一访问原则只是Scala对待字段和方法比Java更统一的一个方面。另一个区别是在Scala中,字段和方法属于同一个命名空间。这使得字段可以覆盖无参数方法。例如,您可以将类ArrayElement中内容的实现从方法更改为字段,而无需修改类Element中内容的抽象方法定义,如清单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
在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。您可以将声明设为惰性val,并且在调用之前不会初始化它。这就是def工作的原因。但是,一种更好的方法不是创建一个隐藏私有构造函数字段的类公共字段,而是将构造函数字段公开,如下所示:
class ArrayElement(val contnts: Array[String]) extends Element {}
因为这里也有父类在起作用,所以最好将其标记为重写;
class ArrayElement(override val contnts: Array[String]) extends Element {}
如果这将是一个无状态数据容器类,那么最好的选择是将其设置为一个case类,该类(除其他外)默认具有公共字段。
case class ArrayElement(override val contnts: Array[String]) extends Element
这是更惯用的scala它将为您提供基于值的equals
、hashCode
、模式匹配、更简单的构造(无需new
)
我浏览了有效的scala幻灯片,在幻灯片10中提到,不要在抽象成员的中使用,而是使用。幻灯片没有详细提到为什么在中使用抽象是反模式。如果有人能解释在抽象方法的特征中使用val vs def的最佳实践,我将不胜感激
我引用马丁·奥德斯基的话: def表单是“按名称”的,每次使用时都会对其右手边进行评估。 val定义的右侧是在定义本身处计算的。 null null 我有点困惑为什么:
我最近在我的Eclipse设置中做了一些改动,主要是我将Java版本从8升级到了15,我花了一段时间才注意到,但是我不能再对我的任何项目进行覆盖测试了,因为它抛出了一个Java.lang.Instrument.IllegalClassFormatException和一个巨大的StackTrace。 它还会弹出一个错误,上面写着“no tests found with test runner'jun
不重复: 此问题不是链接问题的重复。尽管它询问了使用def和val定义函数之间的区别,但代码示例清楚地表明asker对Scala中方法和函数之间的区别感到困惑。该示例根本没有使用def来定义函数。-7小时前的Aaron Novstrup
但是仅仅从使用的角度来看,就像在指南中一样,以下两者之间的区别在哪里 从这个答案中我可以看出,对于getter重写,该值没有存储。getter覆盖与赋值有什么不同吗?也许是代表或者拉丁裔?
问题内容: 例如: Java: 科特林: 我以为它将转换为Java字节码。 问题答案: 这似乎是一个已知的问题在这里。显然,这是一件复杂的事情,不太可能很快解决。 来自安德烈·布雷斯拉夫的原始答复: 不幸的是,这是一个相当深的问题。我们不太可能以您想要的方式使其工作 在问题页面的更下方,您可以看到它在多平台项目方面变得更加复杂。