[前回:インタフェースのデフォルト実装]
(http://qiita.com/yuusuke_s/items/c68fef425fe3cb86d41a#comment-cb4bc98a57b6a14aa5d9)
前回はインタフェースのデフォルト実装を紹介しました。
応用編として、複数のインタフェースを実装(菱形継承)した場合の、同名メソッドの振る舞いについて見てみます。
クラス図
ChildAのメソッドをoverrideした場合
package com.ramda;
public interface Parent {
default String hello() {
return "Hellp Parent.";
}
}
interface ChildA extends Parent {
@Override
public default String hello() {
return "Hellp ChildA.";
}
}
interface ChildB extends Parent {
// not override
}
class Grandchild implements ChildA, ChildB {
}
class Main {
public static void main(String[] args) {
Parent parent = new Grandchild();
System.out.println(parent.hello());
}
}
結果
Hellp ChildA.
より継承関係の近いインタフェースの実装が適用されました。
このように、メソッドの呼び出しに優先順位を付けて、問題を回避しているようです。
では、ChildA、ChildBを両方overrideしたらどうなるでしょう?
ChildA、ChildBのメソッドをoverrideした場合
package com.ramda;
public interface Parent {
default String hello() {
return "Hellp Parent.";
}
}
interface ChildA extends Parent {
@Override
public default String hello() {
return "Hellp ChildA.";
}
}
interface ChildB extends Parent {
@Override
public default String hello() {
return "Hellp ChildB.";
}
}
class Grandchild implements ChildA, ChildB {
}
class Main {
public static void main(String[] args) {
Parent parent = new Grandchild();
System.out.println(parent.hello());
}
}
結果
コンパイルエラーとなりました。
Duplicate default methods named hello with the parameters () and () are inherited from the types ChildB and ChildA
優先順位が付けられない場合、コンパイルエラーとなるようです。
最後に
多重継承をした場合、上記のような衝突が当然おきますが、上手く回避されているようです。
考慮すべき点は多いと思いますが、C++の多重継承のように状態を持つことはないため、
それほどの複雑性はないと感じました。