2

更新:私は質問をより小さく、より正確な例で言い換えました。

次の定義があると仮定します。

class A
trait TraitForA extends A

class D[T]
trait TraitForD extends D[A]

次に、次のようなオブジェクトを作成できます。

scala> new D[A] with TraitForD
res0: D[A] with TraitForD = $anon$1@145d424

ただし、次のオブジェクトを作成することはできません。

scala> new D[A with TraitForA] with TraitForD
<console>:12: error: illegal inheritance;
 anonymous class $anon inherits different type instances of class D:
D[A] and D[A with TraitForA]
             new D[A with TraitForA] with TraitForD
                 ^

トレイトに次の代わりにセルフタイプを使用する場合も同じことが起こりextendsます。

scala> trait TraitForD2 { self: D[A] => }
defined trait TraitForD2

scala> new D[A with TraitForA] with TraitForD2
<console>:12: error: illegal inheritance;
 self-type D[A with TraitForA] with TraitForD2 does not conform to TraitForD2's
selftype TraitForD2 with D[A]
              new D[A with TraitForA] with TraitForD2
                                           ^

上記の作成で(正確に)何が間違っていますか?

私の推測では、それD[A with TraitForA]はタイプとして見られていませんD[A]+Tクラスで共変アノテーションを使用する場合D、両方の例が機能します。

誰かが例が失敗する理由とそれらが機能している理由を説明できますか+T

ボーナス質問:例を使用せずに実行する方法はあり+Tますか?

4

2 に答える 2

3

検討

class C[T]{ def f(t: T): T = t }

C[A with Y]fがかかるA with Yだけで、戻るだけになると言いA with Yます。 C[A]この要求を満たす機能では満たすことができません。したがって、2つは競合しています。

型宣言の成功は、関連するクラスのメソッドの詳細、Z1 with Z2またはその他の結合手段に基づいていないため、エラーC[A]C[A with Y]ある必要があります。

于 2012-06-28T23:02:06.063 に答える
0

分散の問題を確認するために、'TraitForX' にいくつかのメソッドを追加してみましょう。簡単にするために、これらのトレイトをとA1と呼びます。私はあなたがどうやって面白い構造を思いついたのかわかりません - 私は aが aを拡張することさえできることを知りませんでした.それが許されているのは奇妙です!!D1ADtraitclass

trait A
trait A1 extends A { def schoko = 33 }

trait D[T] { def result: T }
trait D1 extends D[A] {
   def result: A = new A {}
}

A1これで、 のインスタンスでは不可能なことを のインスタンスで実行できることがわかりましたA。さらに、D1の具体的な実装がありresultます。

あなたのケースを再現することはまだ可能です:

new D[A] with D1    // works.

new D[A with A1] {  // works.
   def result = new A with A1 {}
   def test = result.schoko
}

testはメソッドを呼び出すことができ、resultDでパラメータ化されているためA with A1(ちなみにこれは同じですA1)、その後 を呼び出すことができますschoko

したがって、次のことは決して機能しません。

new D[A with A1] with D1 {
   def test = result.schoko
}

コンパイラーは と言うでしょう。これは、それ以外のパラメーター化value schoko is not a member of Aされたものを受け入れることを拒否することを意味します。のインスタンスを返すように実装されていたため(これは を認識していません)、ここに固有の競合があります。DresultD1Aschoko


Dが変更されたとき

trait D[+T] { def result: T }

(残りはすべて上記のままです)、問題を「延期」しているだけです:

new D[A with A1] with D1

コンパイラは文句を言うようになりましたerror: overriding method result in trait D of type => A with A1(実際には を実装していないため、これが機能していることを確認しましたresult)。

そのため、バリアンス アノテーションを使用すると、以前はできなかったことができるようになります。を実装していなかった場合result、次のことが完全に可能になります。

trait D2 extends D[A]

new D[A with A1] with D2 {
   def result = new A with A1 {}
}
于 2012-06-30T21:57:17.743 に答える