why using plain val in non-final classes

ε祈祈猫儿з 提交于 2019-12-01 06:28:08

问题


If class is not a final one, it may be extended.

There are two possibilities for values: it may be overridden and should be lazy for it, it may not be overridden and should be final.

If val is final - you may assume that all computations over it would work through class hierarchy. If val may be overriden you should declare it lazy for not becoming broken after extending. You may leave val plain and this gives no guaranties it would be extended in right way.

What use cases imply using plain values?


Example of class initialization failure without lazy values

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)
}

testing it:

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

it works, but further sub-classing broke already existing functionality

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

setting lazy on x2 fixes the case:

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)
}

right initialization order:

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

回答1:


Basically, you are screwing it up.

The problem is not the override, the problem is that you are not paying attention to the order in which things are initialized. There are ways to make it work, and ways to make it not work, and you picked the latter. This works:

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


来源:https://stackoverflow.com/questions/12091689/why-using-plain-val-in-non-final-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!