99

私は効果的なscalaスライドを見ていましたが、スライド10で抽象メンバーvalには決して使用せず、代わりに使用することについて言及しています。このスライドでは、abstractを aで使用することがアンチパターンである理由について詳しく説明していません。誰かが抽象メソッドのトレイトで val と def を使用することに関するベストプラクティスを説明できれば幸いです traitdefvaltrait

4

4 に答える 4

134

は、 、、 、または のいずれdefかで実装できます。したがって、これはメンバーを定義する最も抽象的な形式です。トレイトは通常、抽象的なインターフェイスであるため、必要であるということは、実装がどのように行われるかを示しています。を要求した場合、実装クラスは を使用できません。defvallazy valobjectvalvaldef

Avalは、パス依存型など、安定した識別子が必要な場合にのみ必要です。それは通常必要のないものです。


比較:

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


わかりました、混乱させて @om-nom-nom に答えてください。abstract を使用valすると、初期化の問題が発生する可能性があります。

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

object Fail extends Foo {
  val bar = 33
}

Fail.schoko  // zero!!

これは醜い問題であり、私の個人的な意見では、将来の Scala バージョンではコンパイラーで修正することで解消されるはずですが、そうです、現在これは、abstract を使用すべきではない理由でもありますval

編集(2016 年 1 月): 抽象val宣言をlazy val実装でオーバーライドすることが許可されているため、初期化の失敗も防ぐことができます。

于 2013-10-28T18:24:46.057 に答える
8

valval 宣言の初期化順序が不明確で直感的でないため、トレイトでは使用しないことを好みます。すでに機能している階層に特性を追加すると、以前に機能していたすべてのものを壊す可能性があります。私のトピックを参照してください:非最終クラスで単純な val を使用する理由

この val 宣言の使用に関するすべてのことを念頭に置いておく必要があります。これにより、最終的にエラーが発生します。


より複雑な例で更新

しかし、使わざるを得ない場合もありますval。@0__ が述べたように、安定した識別子が必要な場合がありますが、そうでdefはありません。

彼が何について話しているかを示す例を挙げます。

trait Holder {
  type Inner
  val init : Inner
}
class Access(val holder : Holder) {
  val access : holder.Inner =
    holder.init
}
trait Access2 {
  def holder : Holder
  def access : holder.Inner =
    holder.init
}

このコードは次のエラーを生成します。

 StableIdentifier.scala:14: error: stable identifier required, but Access2.this.holder found.
    def access : holder.Inner =

ちょっと考えてみれば、コンパイラには文句を言う理由があることがわかるでしょう。Access2.accessどうしても戻り値の型を導出できなかった場合。def holder幅広く導入できるということです。呼び出しごとに異なるホルダーを返すことができ、そのホルダーにはさまざまなInnerタイプが組み込まれます。しかし、Java 仮想マシンは、同じ型が返されることを期待しています。

于 2013-10-28T20:23:41.473 に答える