27

以下のエラーが表示されるのはなぜですか? それを回避する方法は?

A と B は (インターフェイス、クラス) のペアにコンパイルされるため、C をコンパイルするときに実装する適切な静的メソッド呼び出しを選択することが問題であると想定しました。優先順位は順序に従うと予想されます。

scala> trait A { def hi = println("A") }
defined trait A

scala> trait B { def hi = println("B") }
defined trait B

scala> class C extends B with A
<console>:6: error: error overriding method hi in trait B of type => Unit;
 method hi in trait A of type => Unit needs `override' modifier
       class C extends B with A

scala> trait A { override def hi = println("A") }
<console>:4: error: method hi overrides nothing
       trait A {override def hi = println("A")}

Ruby ではこれがうまく機能することに注意してください。

>> module B; def hi; puts 'B'; end; end
=> nil
>> module A; def hi; puts 'A'; end; end
=> nil
>> class C; include A; include B; end
=> C
>> c = C.new
=> #<C:0xb7c51068>
>> c.hi
B
=> nil
4

5 に答える 5

54

これは 2.8 および 2.11 で機能し、特性AまたはB:

trait A { def hi = println("A") }
trait B { def hi = println("B") }

class C extends A with B {
  override def hi = super[B].hi
  def howdy = super[A].hi // if you still want A#hi available
}

object App extends Application {
  (new C).hi // prints "B"
}
于 2009-12-03T07:12:46.070 に答える
12

Base次のように、共通の基本特性、たとえば を使用できます。

trait Base {def hi: Unit}
trait A extends Base {override def hi = println("A")}
trait B extends Base {override def hi = println("B")}
class C extends A with B

型階層では、 を呼び出した結果は次のようになります (特性をインスタンス化するために をhi使用することに注意してください)。{}

scala> (new A {}).hi
A

scala> (new B {}).hi
B

scala> (new C).hi
B
于 2009-12-02T23:11:16.147 に答える
4

トレイトは、それを混合するクラスにメソッドを追加します。2 つのトレイトが同じメソッドを追加すると、クラスは 2 つの同一のメソッドになってしまいますが、これはもちろん起こり得ません。

ただし、メソッドがトレイトでプライベートであれば、問題は発生しません。また、メソッドを互いにスタックさせたい場合は、ベース トレイトを定義abstract overrideしてから継承トレイトを定義することができます。ただし、メソッドを定義するにはクラスが必要です。以下に例を示します。

scala> trait Hi { def hi: Unit }
defined trait Hi

scala> trait A extends Hi { abstract override def hi = { println("A"); super.hi } }
defined trait A

scala> trait B extends Hi { abstract override def hi = { println("B"); super.hi } }
defined trait B

scala> class NoHi extends Hi { def hi = () }
defined class NoHi

scala> class C extends NoHi with B with A
defined class C

scala> new C().hi
A
B

ただし、各トレイトから 2 つの個別のメソッドが本当に必要な場合は、 inheritの代わりにcompose する必要があります。

于 2009-12-02T23:27:12.517 に答える
1

これがダイヤモンドの問題です。A からのメソッドと B からのメソッドのどちらをhi継承する必要がありますか? Donが提案したように、共通の基本特性を使用することで、これを回避できます。

于 2009-12-02T23:24:17.420 に答える
0

私は同じ問題を抱えていました.CRUD操作(検索、作成...)を含む特性であるため、同じメソッドで4、5、または6つの特性を持つことができるため、中間特性を作成する必要はありませんでした。さらに、テスト目的でのみこれらの特性を一緒に使用する必要があり、テストを簡単にするためだけにプロジェクトの構造を変更することはできるだけ避けようとしています。したがって、これらの特性をさまざまなオブジェクトに単純に実装しました。

class somethingToTest {
  object AImpl extends ATrait 
  object BImpl extends BTrait

  val a = AImpl.methodDuplicated()
  val b = BImpl.methodDuplicated()
}

これはおそらく特性を使用する最も賢い方法ではありませんが、プロジェクトのコードを変更する必要はありません。テストにもう少しコードを追加することを意味するだけです。

于 2014-09-08T14:48:50.643 に答える