JDK8から盛り込まれたVirtualExtensionMethods。
これで、インタフェースにデフォルトな実装を持つことが出来るようになる。
(Iterable.
ただ、これによって、1クラスに複数実装可能であるインタフェースは、複数の実装を持つといった問題がある。
(C++と違ってインタフェースにはフィールドを持つことは無いので、そこまで面倒なことにはならない?)
仕様で定義されてると思うのだけど、英語はわからんちんだったのでJDK8-EAで試した。
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だかなんだか呼び名があった気がするが、これがそうなのかな。)