Scala のクラスは単一継承だけど、トレイトは複数継承できるので菱形継承問題が起きる。菱形継承問題というのは次のようなものだ。
greet メソッドを定義した TraitA と、それを継承してそれぞれ別の greet メソッドを実装した TraitB と TraitC があるとする。
scala> trait TraitA { | def greet(): Unit | } defined trait TraitA scala> trait TraitB extends TraitA { | def greet(): Unit = println("Good morning!") | } defined trait TraitB scala> trait TraitC extends TraitA { | def greet(): Unit = println("Good evening!") | } defined trait TraitC
ここで TraitB と TraitC の両方を継承したクラスを考えよう。すると、継承の系統図が菱形になる。で、どこが問題かというと、greet メソッドの実装が衝突している、ということだ。これを菱形継承問題という。
Scala で単純にこういう継承を作るとエラーになる。
scala> class ClassA extends TraitB with TraitC <console>:13: error: class ClassA inherits conflicting members: method greet in trait TraitB of type ()Unit and method greet in trait TraitC of type ()Unit (Note: this can be resolved by declaring an override in class ClassA.) class ClassA extends TraitB with TraitC ^
TraitB と TraitC を継承した ClassA で greet メソッドが衝突していると怒られている。
これを解決するには ClassA で greet メソッドをオーバーライドしてやればいい。
scala> class ClassA extends TraitB with TraitC { | override def greet(): Unit = println("How are you?") | } defined class ClassA
継承元の TraitB の greet メソッドを呼び出したいときには次のように super キーワードを使う。[ ] の中に呼び出したいほうのトレイト名を書けばいい。
scala> class ClassB extends TraitB with TraitC { | override def greet(): Unit = super[TraitB].greet() | } defined class ClassB
呼び出した結果はそれぞれ次のようになる。
scala> (new ClassA).greet() How are you?
scala> (new ClassB).greet() Good morning!