7

Baseいくつかのスタッキング トレイトが定義されている抽象基本クラス ( ) があります ( StackingTrait)。

trait Base {
  def foo
}
trait StackingTrait extends Base {
  abstract override def foo { super.foo }
}

次の構文を使用してサブクラスを実装すると非常に便利ですが、これは機能しません。なぜなら、コンパイラは foo を宣言してから再コンパイルする必要があると言うoverrideからです。これはクラスでabstract overrideあるため無効です。Impl

class Impl extends Base with StackingTrait {
  def foo {}
}

そのような構文が許可されない正当な理由が思いつきません。foo は論理的に定義されてImplいるため、スタッキングが発生する順序は概念的に同じままです。

注:私が望むのと同じことを効果的に行うこの回避策を見つけましたが、ヘルパークラスの必要性により、より良い解決策が必要になります。

class ImplHelper extends Base {
  def foo {}
}
class Impl extends ImplHelper with StackingTrait

目的の構文がコンパイルされないのはなぜですか? また、洗練された解決策はありますか?

4

2 に答える 2

4

エラー メッセージはわかりにくいかもしれませんが、動作は正しいと理解しています。 はinのようにfoo宣言されているため、混在する具象クラスには、(線形化順序に対して) beforeの具象 ( としてマークされていない) の実装が必要です。これは、線形化の順序で直前のトレイトを参照するためです。そのため、確実にbeforeの具体的な実装が必要であり、混同されていないと意味がありません。abstract overrideStackingTraitStackingTraitabstractfoo StackingTraitsuperfooStackingTraitsuper.foo

これを行う場合:

class Impl extends Base with StackingTrait {
  def foo {}
}

線形化の順序はBase<- StackingTrait<-Implです。前の唯一の特性StackingTraitBaseBaseの具体的な実装を定義していませんfoo

しかし、これを行うと:

traitImplHelper extends Base {
  def foo {}
}
class Impl extends ImplHelper with StackingTrait

線形化の順序は次のようになります: Base<- ImplHelper<- StackingTrait<-Impl ここImplHelperには の具体的な定義が含まれており、foo間違いなくの StackingTraitです。

価値があるのは、(のように)ImplHelper後で混合した場合、同じ問題が再び発生し、コンパイルに失敗することです。StackingTraitclass Impl extends StackingTrait with ImplHelper

したがって、これは私にはかなり一貫しているように見えます。あなたが意図したようにコンパイルする方法を知りません。ただし、 orを簡単に記述できるようにすることよりも、簡単に記述できるようにする (別のクラス/特性を必要とせずにすぐにImpl定義できるようにする)ことに関心がある場合は、次のようにすることもできます。fooBaseStackingTrait

trait Base {
  protected def fooImpl
  def foo { fooImpl } 
}
trait StackingTrait extends Base {
  abstract override def foo { super.foo }
}

class Impl extends Base with StackingTrait {
  protected def fooImpl {}
}

元のバージョンと同じように、各具象クラスを強制的にfoo( の形式でfooImpl) 実装すると、今度はコンパイルされます。ここでの欠点は、 while をfooImpl呼び出しsuper.fooてはならない (意味がなく、無限ループに入る) ことです。コンパイラはそれについて警告しません。

于 2013-01-05T11:09:03.927 に答える
0

トレイトを拡張する代わりに、例で述べたように自己型を使用することができます。 https://docs.scala-lang.org/tour/self-types.html .

于 2020-04-16T17:52:37.513 に答える