Jawne wywoływanie domyślnej metody w Javie

247

Java 8 wprowadza domyślne metody zapewniające możliwość rozszerzenia interfejsów bez potrzeby modyfikowania istniejących implementacji.

Zastanawiam się, czy możliwe jest jawne wywołanie domyślnej implementacji metody, gdy metoda ta została zastąpiona lub nie jest dostępna z powodu sprzecznych domyślnych implementacji w różnych interfejsach.

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

Biorąc pod uwagę powyższy kod, jak byś zadzwonił A.foo()z metody klasy B?

GOTO 0
źródło
Czy możesz mi powiedzieć, dlaczego masz implementację metody foo () w interfejsie A ??.
Maciej Cygan
20
@MaciejCygan Dozwolone w Javie 8
Rohit Jain

Odpowiedzi:

330

Zgodnie z tym artykułem dostęp domyślnej metody w interfejsie Aza pomocą

A.super.foo();

To może być wykorzystywane w następujący sposób (zakładając, interfejsy Ai Coba mają metody domyślne 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
    }
}

Ai Cmogą mieć zarówno .foo()metody, jak i wybraną konkretną domyślną implementację lub możesz użyć jednej (lub obu) jako części nowej foo()metody. Możesz także użyć tej samej składni, aby uzyskać dostęp do wersji domyślnych innymi metodami w klasie implementującej.

Formalny opis składni wywołania metody można znaleźć w rozdziale 15 JLS .

Richard Tingle
źródło
14
Pamiętaj również, że jeśli A extends SomeOtherInterfacei SomeOtherInterfacema default Type method(), to nie możesz po prostu zadzwonić SomeOtherInterface.super.method()z ChildClass. Można dzwonić tylko domyślne metody interfejsów wymienionych w ChildClass's implementsklauzuli, a nie ich interfejsów dominujących metod.
gvlasov
1
@Suseika dobry punkt, tak samo jak nie ma super.super.someMethod();(bo to byłoby okropne)
Richard Tingle
@gvlasov dobry punkt, ale jak uzyskać dostęp do domyślnej metody interfejsu nadrzędnego z interfejsu podrzędnego, czy jest to możliwe? Aktualizacja .......... Tak Możliwe, bardziej konkretne wyjaśnienie tutaj stackoverflow.com/a/24280376/3791156
Raaghu
@RichardTingle bezbłędna odpowiedź!
gaurav
17

Poniższy kod powinien działać.

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

Wynik:

B.foo
A.foo
Abhijith Nagarajan
źródło
Myślę, że to najlepszy przykład opisujący powyższe pytanie. Dzięki
Hemanth Peela,
8

Ta odpowiedź jest napisana głównie dla użytkowników, którzy pochodzą z pytania 45047550, które jest zamknięte.

Interfejsy Java 8 wprowadzają niektóre aspekty wielokrotnego dziedziczenia. Metody domyślne mają zaimplementowaną treść funkcji. Aby wywołać metodę z superklasy, możesz użyć słowa kluczowego super, ale jeśli chcesz to zrobić za pomocą super interfejsu, musisz jawnie nazwać ją.

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

Wynik:

Witaj ParentClass!
Witaj InterfaceFoo!
Witaj InterfaceBar!

Dávid Horváth
źródło
3

Nie musisz zastępować domyślnej metody interfejsu. Po prostu nazwij to tak:

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

Wynik:

A.foo

Masudul
źródło
9
OP mówi: „[czy] można jawnie wywołać domyślną implementację metody, gdy ta metoda została zastąpiona”
dasblinkenlight