为什么在非最终类中使用普通val

时间:2012-08-23 12:32:16

标签: scala lazy-evaluation final

如果课程不是最后一课,可以延期。

值有两种可能性:它可能被覆盖并且应该是惰性的,它可能不会被覆盖并且应该是最终的。

如果val是final - 你可以假设它上面的所有计算都可以通过类层次结构来完成。如果val可能被覆盖,你应该声明它是懒惰的,以便在扩展后不会被破坏。你可以保留val平原,这不保证它会以正确的方式延伸。

哪些用例暗示使用普通值?


没有延迟值的类初始化失败的示例

abstract class A {
  lazy val x1 : String = throw new Exception()
  val x2 : String = "mom"
  val x3 : String = x1 + ", " + x2
  println("A: " + x3)
}
class B extends A {
  override lazy val x1: String = "hello"
  println("B: " + x3)
}
class C extends B {
  override val x2: String = "dad"
  println("C: " + x3)
}

测试它:

scala> new B
A: hello, mom
B: hello, mom
res8: B = B@7e2bd615

它有效,但进一步的子分类破坏了现有的功能

scala> new C
A: hello, null
B: hello, null
C: hello, null
res5: C = C@52a53948

在x2上设置lazy修复了这个案例:

abstract class A {
  lazy val x1 : String = throw new Exception()
  lazy val x2 : String = "mom"
  val x3 : String = x1 + ", " + x2
  println("A: " + x3)
}
class B extends A {
  override lazy val x1: String = "hello"
  println("B: " + x3)
}
class C extends B {
  override lazy val x2: String = "dad"
  println("C: " + x3)
}

正确的初始化顺序:

scala> new C
A: hello, dad
B: hello, dad
C: hello, dad
res6: C = C@5e970110

1 个答案:

答案 0 :(得分:3)

基本上,你搞砸了。

问题不在于覆盖,问题在于您没有注意事物初始化的顺序。有一些方法可以使它工作,以及使它不起作用的方法,你选择了后者。这有效:

scala> class C extends { override val x2: String = "dad" } with B {
     |   println("C: " + x3)
     | }
defined class C

scala> new C
A: hello, dad
B: hello, dad
C: hello, dad
res0: C = C@356e3aaf