覆盖 'val' 时出现意外结果
Unexpected Result when Overriding 'val'
在 Scala 2.10.4 中,给定以下 class:
scala> class Foo {
| val x = true
| val f = if (x) 100 else 200
| }
defined class Foo
以下两个例子对我来说很有意义:
scala> new Foo {}.f
res0: Int = 100
scala> new Foo { override val x = false}.f
res1: Int = 200
但是,为什么不调用 return 100
?
scala> new Foo { override val x = true }.f
res2: Int = 200
因为 vals 没有被多次初始化,x
在 [=15] 的初始化过程中实际上是 null
(或者 false
默认 Boolean
) =],然后在您的示例中扩展 Foo
的匿名 class 中进行初始化。
我们可以使用 AnyRef
:
更轻松地对其进行测试
class Foo {
val x = ""
val f = if (x == null) "x is null" else "not null"
}
scala> new Foo { override val x = "a" }.f
res10: String = x is null
scala> new Foo {}.f
res11: String = not null
Scala FAQ 中有完整的解释。摘录:
Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val.
避免这种情况的一个简单方法是使用惰性 val 或 def,如果被引用的 val 可能被覆盖。
此外,您可以使用 -Xcheckinit
编译器标志来警告您潜在的此类初始化错误。
在 Scala 2.10.4 中,给定以下 class:
scala> class Foo {
| val x = true
| val f = if (x) 100 else 200
| }
defined class Foo
以下两个例子对我来说很有意义:
scala> new Foo {}.f
res0: Int = 100
scala> new Foo { override val x = false}.f
res1: Int = 200
但是,为什么不调用 return 100
?
scala> new Foo { override val x = true }.f
res2: Int = 200
因为 vals 没有被多次初始化,x
在 [=15] 的初始化过程中实际上是 null
(或者 false
默认 Boolean
) =],然后在您的示例中扩展 Foo
的匿名 class 中进行初始化。
我们可以使用 AnyRef
:
class Foo {
val x = ""
val f = if (x == null) "x is null" else "not null"
}
scala> new Foo { override val x = "a" }.f
res10: String = x is null
scala> new Foo {}.f
res11: String = not null
Scala FAQ 中有完整的解释。摘录:
Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val.
避免这种情况的一个简单方法是使用惰性 val 或 def,如果被引用的 val 可能被覆盖。
此外,您可以使用 -Xcheckinit
编译器标志来警告您潜在的此类初始化错误。