web-dev-qa-db-ja.com

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

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?
    }
}

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

207
GOTO 0

この記事 により、インターフェース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
    }
}

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

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

269
Richard Tingle

以下のコードが機能するはずです。

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
14

この回答は、主に質問 4504755 が終了しているために来ているユーザー向けに書かれています。

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!
Hello InterfaceFoo!
Hello InterfaceBar!

7
Dávid Horváth

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

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

3
Masudul