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!