ダイヤモンド継承でコンパイルエラーになる例
同じシグニチャを持つ複数のインターフェースをimplementsした場合、コンパイルエラーになります。
public interface ifParent { default void X(){ System.out.println("interfaseParent"); } }
public interface ifA extends ifParent{ @Override default void X(){ System.out.println("interfaseA"); } }
public interface ifB extends ifParent{ @Override default void X(){ System.out.println("interfaseB"); } }
public class classC implements ifA ,ifB { //ここでコンパイルエラーになる。 public static void main(String[] args) { classC c = new classC(); c.X(); } }
上記のソースをクラス図で表現すると以下のとおりです。
classCがifAとifBをimplementsしたタイミングでコンパイルエラーになります。
これはclassCから見た場合、ifAとifBが同階層にあり、両者ともdefaultメソッドをOverrideしているためです。
これを防ぐには以下のようにclassCでXメソッドをOverrideする必要があります。
public class classC implements ifA ,ifB { public static void main(String[] args) { classC c = new classC(); c.X(); //classC } @Override public void X(){ System.out.println("classC"); } }
ダイヤモンド継承でコンパイルエラーにならない例
複数のインターフェースが同階層にあってもメソッドが異なる階層(距離が離れている場合)近いほうのメソッドが呼ばれるため、コンパイルエラーになりません。
public interface ifParent { default void X(){ System.out.println("interfaseParent"); } }
public interface ifA extends ifParent{ @Override default void X(){ System.out.println("interfaseA"); } }
public interface ifB extends ifParent{ }
public class classC implements ifA ,ifB { public static void main(String[] args) { classC c = new classC(); c.X(); //interfaseA } }
上記ソースをクラス図で表現すると以下のとおり。
ダイヤモンド継承でコンパイルエラーになる例との違いはifBでOverrideしていない点。
より近い方でOverrideしたifAのXメソッドが呼ばれます。