LoginSignup
15
19

More than 5 years have passed since last update.

Java インターフェースデフォルト実装を継承して呼び出す方法

Last updated at Posted at 2016-01-26

インターフェースのデフォルト実装が継承した子クラスや子インターフェースから呼び出せることを今日知ったので調べてまとめることにしました。

呼び出し方法

結論から言うと、

親インターフェース名.super.メソッド名();

で呼び出せます。これ以降でいろんなパターンで試したことを書きます。

子クラスから親インターフェースのdefault実装を呼び出す

基礎。
普通にEclipseでdefault実装を持ってる実装クラスを作って「ソース」→「メソッドのオーバーライド実装」で保管されました。

Interface1.java
public interface Interface1 {
    default void test() {
        System.out.println("Interface1");
    }
}
ImplA.java
public class ImplA implements Interface1 {
    @Override
    public void test() {
        Interface1.super.test();
    }
}

ImplA#testの実行結果は

Interface1

子インターフェースから親インターフェースのdefault実装を呼び出す

子クラスの方法と同じです。

Interface2.java
public interface Interface2 extends Interface1 {
    @Override
    default void test() {
        Interface1.super.test();
    }
}
ImplB.java
public class ImplB implements Interface2 {

}

ImplB#testの実行結果は

Interface1

子クラスから複数親インターフェースのdefault実装を呼び出す

なんでsuperの前にインターフェース名を書かないといけないのかが、
ここでやっと分かりました。

Interface3.java
public interface Interface3 {
    default void test() {
        System.out.println("Interface3");
    }
}
ImplC.java
public class ImplC implements Interface1, Interface3 {
    @Override
    public void test() {
        Interface1.super.test();
        Interface3.super.test();
    }
}

ImplC#testの実行結果は

Interface1
Interface3

子インターフェースから複数親インターフェースのdefault実装を呼び出す

public interface Interface4 extends Interface1, Interface3 {
    @Override
    default void test() {
        Interface1.super.test();
        Interface3.super.test();
    }
}
public class ImplD implements Interface4 {
}

ImplD#testの実行結果は

Interface1
Interface3

ダメなパターン

型階層で2つ以上飛ばして、直接、superインターフェースのdefault実装は呼び出せない。

Interface5.java
public interface Interface5 extends Interface1 {
}
Interface6.java
public interface Interface6 extends Interface5 {
    @Override
    default void test() {
        Interface1.super.test();//コンパイルエラー
    }
}

下記はOK。

Interface7.java
public interface Interface7 extends Interface5 {
    @Override
    default void test() {
        Interface5.super.test();
    }
}

結果Interface1のデフォルト実装が呼び出される。

で、

extendsに入ってたらOKなのか?と思ってやってみたけど、下記もコンパイルエラー

public interface Interface8 extends Interface5, Interface1 {
    @Override
    default void test() {
        Interface1.super.test();//コンパイルエラー
    }
}

おまけ

親インターフェース名.super.メソッド名();

この書き方はインターフェースの継承・実装限定の記述っぽい。
普通のクラス継承で使うとコンパイルエラーになる。

Abs.java
public class Abs {
    public void test() {
        System.out.println("Abs1");
    }
}
AbsImpl.java
public class AbsImpl extends Abs {
    @Override
    public void test() {
        Abs.super.test();//コンパイルエラー
    }
}

感想

複数親を呼び出せるのは便利!だけど使いこなせる気がしない。

15
19
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
19