3

クラスが最終クラスでない場合は、拡張される場合があります。

値には2つの可能性があります。オーバーライドされる可能性があり、怠惰である必要があります。オーバーライドされない可能性があり、最終的な値である必要があります。

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でレイジーを設定すると、ケースが修正されます。

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
4

1 に答える 1

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
于 2012-08-23T16:12:59.050 に答える