VirtualExtensionMethodsと多重継承

JDK8から盛り込まれたVirtualExtensionMethods。
これで、インタフェースにデフォルトな実装を持つことが出来るようになる。
(Iterable.forEachなどに使ってる)


ただ、これによって、1クラスに複数実装可能であるインタフェースは、複数の実装を持つといった問題がある。
(C++と違ってインタフェースにはフィールドを持つことは無いので、そこまで面倒なことにはならない?)


仕様で定義されてると思うのだけど、英語はわからんちんだったのでJDK8-EAで試した。



使うJavaバージョン。

java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b88)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b30, mixed mode)


同じメソッド(defaultあり)を持つ異なるインタフェースを用意。

IHoge.java

public interface IHoge {
    default String getMessage() {
            return "Hoge";
    };
}

IFuga.java

public interface IFuga {
    default String getMessage() {
            return "Fuga";
    };
}

インタフェースで多重継承するが、明示的に選ばなければコンパイルエラーになる

public interface IMoge extends IHoge,IFuga { } // コンパイルエラー

インタフェースで多重継承するが、明示的にIFugaの実装をデフォルトとする

public interface IMoge extends IHoge,IFuga {
    default String getMessage(){
        return IFuga.super.getMessage();
    }
}

"Fuga"が返却される。

インタフェースで多重継承するが、未実装にする

public interface IMoge extends IHoge,IFuga {
    String getMessage();
}

ただ、利用時には実装しなければならない。

public class MessageImpl implements IMoge{
    public  String getMessage() { return "Impl"; }
}

IMogeの親インタフェースであるIHogeの実装を呼び出すことはできない(と思う。)

public class MessageImpl implements IMoge{
    public  String getMessage() { return IHoge.super.getMessage(); } // コンパイルエラー
}

継承関係が複雑な感じの場合。

B 親インタフェース(default有り)
/ \
D1 D2 子インタフェース(D2のみdefault有り)
\ /
E 実装クラス
public class Main {
    interface B{
        default String getMessage(){ return "B"; }
    }
    interface D1 extends B{            
    }
    interface D2 extends B{
        default String getMessage(){ return "D2"; }
    }
    
   static class E implements D1, D2{}
    
    public static void main(String[] args) {
        System.out.println(new E().getMessage()); // "D2"
    }
}

Eから見て最も浅いところにあるインタフェースのデフォルト実装を呼び出す模様。
なのでD2のデフォルト実装を呼び出している?
(implements の D1, D2の順番は関係ないっぽい。継承の順序を決めるアルゴリズムでC3だかなんだか呼び名があった気がするが、これがそうなのかな。)