Javaでデフォルトのメソッドを明示的に呼び出す


247

Java 8では、既存の実装を変更せずにインターフェースを拡張する機能を提供するデフォルトのメソッドが導入されています

メソッドがオーバーライドされている場合、または異なるインターフェイスでデフォルト実装が競合しているために使用できない場合に、メソッドのデフォルト実装を明示的に呼び出すことができるかどうか疑問に思います。

interface A {
    default void foo() {
        System.out.println("A.foo");
    }
}

class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }
    public void afoo() {
        // how to invoke A.foo() here?
    }
}

上記のコードを考慮してA.foo()、クラスBのメソッドからどのように呼び出しますか?


インターフェースA内にfoo()メソッドの実装がある理由を教えてください。
Maciej Cygan 2013年

20
@MaciejCygan Java 8で許可
Rohit Jain

回答:


330

あたりとして、この記事では、インターフェイスにデフォルトメソッドにアクセスするA使用して

A.super.foo();

これは次のように使用できます(インターフェースAC両方にデフォルトのメソッドがあると仮定foo()

public class ChildClass implements A, C {
    @Override    
    public void foo() {
       //you could completely override the default implementations
       doSomethingElse();
       //or manage conflicts between the same method foo() in both A and C
       A.super.foo();
    }
    public void bah() {
       A.super.foo(); //original foo() from A accessed
       C.super.foo(); //original foo() from C accessed
    }
}

Aまた、C両方に.foo()メソッドを含めることができ、特定のデフォルト実装を選択するか、新しいfoo()メソッドの一部として1つ(または両方)を使用できます。同じ構文を使用して、実装クラス内の他のメソッドのデフォルトバージョンにアクセスすることもできます。

メソッド呼び出し構文の正式な説明は、JLSの15章にあります。


14
またA extends SomeOtherInterface、とSomeOtherInterfaceがある場合、ChildClassからdefault Type method()単に呼び出すことはできませんSomeOtherInterface.super.method()。親インターフェースのメソッドではなく、ChildClass's implements句で列挙されたインターフェースのデフォルトメソッドのみを呼び出すことができます。
gvlasov

1
@Suseikaの良い点、ないのと同じsuper.super.someMethod();(それは恐ろしいので)
Richard Tingle

@gvlasov良い点ですが、子インターフェイスから親インターフェイスのデフォルトメソッドにアクセスする方法はありますか?アップデート..........はい可能、より具体的な説明はこちらstackoverflow.com/a/24280376/3791156
Raaghu

@RichardTingle完璧な答え!
gaurav

17

以下のコードは動作するはずです。

public class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    void aFoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
        B b = new B();
        b.foo();
        b.aFoo();
    }
}

interface A {
    default void foo() {
        System.out.println("A.foo");
    }
}

出力:

B.foo
A.foo

これは上記の質問を説明する最良の例だと思います。おかげで
ヘマンス・ピーラ

8

この回答は主に、クローズされている質問45047550からのユーザー向けに書かれています。

Java 8インターフェースは、多重継承のいくつかの側面を導入します。デフォルトのメソッドには、実装された関数本体があります。スーパークラスからメソッドを呼び出すには、キーワードを使用できますが、superこれをスーパーインターフェイスで作成する場合は、明示的に名前を付ける必要があります。

class ParentClass {
    public void hello() {
        System.out.println("Hello ParentClass!");
    }
}

interface InterfaceFoo {
    default public void hello() {
        System.out.println("Hello InterfaceFoo!");
    }
}

interface InterfaceBar {
    default public void hello() {
        System.out.println("Hello InterfaceBar!");
    }
}

public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
    public void hello() {
        super.hello(); // (note: ParentClass.super is wrong!)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    }

    public static void main(String[] args) {
        new Example().hello();
    }
}

出力:

こんにちはParentClass!
こんにちはInterfaceFoo!
こんにちはInterfaceBar!


3

インターフェースのデフォルトのメソッドをオーバーライドする必要はありません。次のように呼び出すだけです。

public class B implements A {

    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    public void afoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
       B b=new B();
       b.afoo();
    }
}

出力:

A.foo


9
OPによると、「メソッドがオーバーライドされたときに、メソッドのデフォルト実装を明示的に呼び出すことは可能ですか」
dasblinkenlight
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.