1. ホーム
  2. scala

[解決済み] Scalaのtraitでvalとdefの使い分けは?

2023-01-02 03:54:58

質問

私は 効果的なscalaのスライド を見ていたら、スライド 10 で、決して val の中で trait を使い、抽象的なメンバーには def を使用します。このスライドでは、なぜ抽象的な val の中で trait はアンチパターンです。抽象的なメソッドのためにtraitでvalとdefを使用することについてのベストプラクティスを説明できる人がいれば、私は感謝します。

どのように解決するのですか?

A def のどちらかで実装することができます。 def , a val , a lazy val または object . つまり、これはメンバを定義する最も抽象的な形式なのです。traitsは通常抽象的なインタフェースなので、例えば val というのは どのように を述べているのです。もし、あなたが val を要求した場合、実装クラスは def .

A val は安定した識別子が必要な場合のみ、例えばパスに依存する型のために必要です。通常は必要ないものです。


比べてみてください。

trait Foo { def bar: Int }

object F1 extends Foo { def bar = util.Random.nextInt(33) } // ok

class F2(val bar: Int) extends Foo // ok

object F3 extends Foo {
  lazy val bar = { // ok
    Thread.sleep(5000)  // really heavy number crunching
    42
  }
}

もし、あなたが

trait Foo { val bar: Int }

を定義することはできないでしょう。 F1 または F3 .


OK、そしてあなたを混乱させ、@om-nom-nom-using abstractに答えるために val を使用すると、初期化の問題が発生する可能性があります。

trait Foo { 
  val bar: Int 
  val schoko = bar + bar
}

object Fail extends Foo {
  val bar = 33
}

Fail.schoko  // zero!!

これは醜い問題で、私の個人的な意見では、将来の Scala のバージョンではコンパイラで修正することで解消されるはずですが、そう、現在のところ、これは、抽象的な val s.

Edit (2016年1月)を参照してください。抽象的な val 宣言を lazy val を実装することで、初期化の失敗を防ぐこともできます。