0

この質問は、抽象型をオーバーライドするCakeパターンの質問に続き、UpperTypeBoundsでは機能しません。トレイトの抽象型を。でオーバーライドしたい<:。前のリンクは、トレイトSで記述して線形化の順序を変更することで構成されるソリューションを提供します。ただし、次のコードでthis: Cake with S名前を付けたコントロールの抽象化を追加しました。controlその中のメソッドを呼び出したいt

trait A {
  def ping = println("ping")
}

trait Cake {
  type T
}

trait S { this: Cake with S =>
  type T <: A with S
  def t: T
  def s = println("test")
  // def control(c: =>T): T = c // compile
  // def control(c: =>T): T = c.s // does not compile
  def control(c: =>T): T = c.t // does not compile
  t.ping
  t.s
}

しかし、このコードは私が説明できないコンパイルエラーを引き起こします

 found   : S.this.T#T
 required: S.this.T
         def control(c: =>T): T = c.t
                                    ^

なにが問題ですか ?

4

1 に答える 1

1
def control(c: =>T): T

リターンタイプありS#T。明らかに、cタイプTもあります。したがって、次のように戻りcます。

def control(c: =>T): T = c

コンパイルしますが、 returnタイプが。であるため、returningc.sはコンパイルされません。 戻り型が。であるため、コンパイルされません。sUnitc.tS#T#T

したがって、以下がコンパイルされます。

def control(c: =>T): T#T = c.t

ここで起こっていることすべての背後にある詳細は、一般的に少し重要ですので、詳細については、「タイププロジェクション」と「パス依存型」をグーグルで検索することをお勧めします。

基本的に、発生しているのcはタイプT、whereT <: A with Sです。したがって、のTすべてSのメンバーが必要であり、そのうちの1つはとして定義されている必要がありdef t: Tます。ただし、これTは必ずしも私たちと同じではないため、例Tを呼び出すときに準拠していませんc.t。必要なのは、TタイプのT(または同等に、T's T、またはTタイプメンバーののT)です。ここT#Tに私たちが欲しいものを正確に示します。

于 2013-01-10T17:44:10.060 に答える