Explizites Aufrufen einer Standardmethode in Java


247

In Java 8 werden Standardmethoden eingeführt , mit denen Schnittstellen erweitert werden können, ohne dass vorhandene Implementierungen geändert werden müssen.

Ich frage mich, ob es möglich ist, die Standardimplementierung einer Methode explizit aufzurufen, wenn diese Methode überschrieben wurde oder aufgrund widersprüchlicher Standardimplementierungen in verschiedenen Schnittstellen nicht verfügbar ist.

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

Wie würden Sie unter Berücksichtigung des obigen Codes A.foo()eine Methode der Klasse B aufrufen ?


Können Sie mir sagen, warum Sie die Implementierung Ihrer foo () -Methode in Ihrer Schnittstelle A haben?
Maciej Cygan

20
@ MaciejCygan Es ist in Java 8 erlaubt
Rohit Jain

Antworten:


330

Gemäß diesem Artikel gelangen Sie Standardmethode in der Schnittstelle Amit

A.super.foo();

Dies kann wie folgt verwendet werden (vorausgesetzt, Schnittstellen Aund Cbeide haben Standardmethoden 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
    }
}

Aund Ckönnen beide .foo()Methoden haben und die spezifische Standardimplementierung kann ausgewählt werden oder Sie können eine (oder beide) als Teil Ihrer neuen foo()Methode verwenden. Sie können dieselbe Syntax auch verwenden, um auf die Standardversionen in anderen Methoden Ihrer Implementierungsklasse zuzugreifen.

Eine formale Beschreibung der Syntax des Methodenaufrufs finden Sie in Kapitel 15 des JLS .


14
Beachten Sie auch, dass Sie, wenn A extends SomeOtherInterfaceund SomeOtherInterfacehaben default Type method(), nicht einfach SomeOtherInterface.super.method()von ChildClass aus anrufen können. Sie können nur Standardmethoden für Schnittstellen aufrufen, die in der Klausel ChildClass's aufgeführt implementssind, nicht die Methoden der übergeordneten Schnittstellen.
Gvlasov

1
@Suseika guter Punkt, genauso wie es keinen gibt super.super.someMethod();(weil das schrecklich wäre)
Richard Tingle

@gvlasov guter Punkt, aber wie kann man über eine untergeordnete Schnittstelle auf die Standardmethode einer übergeordneten Schnittstelle zugreifen? Ist das möglich? Update .......... Ja Möglich, die konkretere Erklärung hier stackoverflow.com/a/24280376/3791156
Raaghu

@ RichardTingle makellose Antwort!
Gaurav

17

Der folgende Code sollte funktionieren.

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");
    }
}

Ausgabe:

B.foo
A.foo

Ich denke, dies ist das beste Beispiel, das die obige Frage beschreibt. Vielen Dank
Hemanth Peela

8

Diese Antwort richtet sich hauptsächlich an Benutzer, die aus der geschlossenen Frage 45047550 kommen .

Java 8-Schnittstellen führen einige Aspekte der Mehrfachvererbung ein. Standardmethoden haben einen implementierten Funktionskörper. Um eine Methode aus der Superklasse aufzurufen, können Sie das Schlüsselwort verwenden super. Wenn Sie dies jedoch mit einer Superschnittstelle erstellen möchten, müssen Sie diese explizit benennen.

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();
    }
}

Ausgabe:

Hallo ParentClass!
Hallo InterfaceFoo!
Hallo InterfaceBar!


3

Sie müssen die Standardmethode einer Schnittstelle nicht überschreiben. Nennen Sie es einfach wie folgt:

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();
    }
}

Ausgabe:

A.foo


9
OP sagt: "[ist es] möglich, die Standardimplementierung einer Methode explizit aufzurufen, wenn diese Methode überschrieben wurde"
dasblinkenlight
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.