これが正しい解決策かどうかはわかりませんが、trait B
拡張A
(およびオーバーライドb
) している場合は、すべて正常にコンパイルされます。
まず、定義して、質問に提示するようにしましょA
うAA
。
C:\Users\VonC>scala
Welcome to Scala version 2.8.0.RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class A {
| def b { println("A b") }
| }
defined class A
scala> new A
res5: A = A@153bedc4
scala> res5.b
A b
scala> abstract class AA extends A {
| override def b
| }
defined class AA
あなたがしたこと:
scala> trait B {
| override def b { println("B b") }
| }
<console>:6: error: method b overrides nothing
override def b { println("B b") }
^
特性 B で試したこと (「override
」を追加できるようにするため):
scala> trait B extends A {
| override def b { println("B b") }
| }
defined trait B
だから今:
scala> class C extends AA with B {}
defined class C
scala> new C
res7: C = C@1497b7b1
scala> res7.b
B b
正しいb
オーバーライドされたメソッドが呼び出されますC.b
明らかな「矛盾」については、Scala for Java Refugees Part 5: Traits and Types を参照してください。
まず、いつも悩ましいoverride
キーワードがあります。基本的な OOP に関する記事で、スーパークラスのメソッドをオーバーライドするメソッドはオーバーライド修飾子を使用して宣言する必要があると述べました。当時、私はそれを@Override
アノテーションの使用を義務付ける言語になぞらえ、その主な目的はグッド プラクティスを強制することでした。
トレイトの力の本当の鍵は、コンパイラが継承クラスでそれらを処理する方法です。
特性は実際にはミックスインであり、真の親クラスではありません。
非抽象的特性メンバーは、物理的にクラスの一部として、実際には継承クラスに含まれます。まあ、物理的にではありませんが、あなたは写真を手に入れます。
これは、コンパイラが非抽象メンバーでカット アンド ペーストを実行し、それらを継承クラスに挿入するかのようです。これは、継承パスにあいまいさがなく、ひし形の問題がないことを意味します。
したがってoverride
、2 番目の例ではキーワードは必要ありません。