Явно викликає метод 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?


Чи можете ви сказати мені, чому ви маєте реалізацію свого методу foo () всередині вас інтерфейсом A ??.
Maciej Cygan

20
@MaciejCygan Це дозволено в Java 8
Rohit Jain

Відповіді:


330

Відповідно до цієї статті ви отримуєте доступ до методу за замовчуванням в інтерфейсі, Aвикористовуючи

A.super.foo();

Це можна використати так (якщо інтерфейси Aі Cобидва мають методи за замовчуванням 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()методу. Ви також можете використовувати той же синтаксис для доступу до версій за замовчуванням в інших методах вашого класу реалізації.

Офіційний опис синтаксису виклику методу можна знайти в главі 15 JLS .


14
Також зауважте, що якщо A extends SomeOtherInterfaceі SomeOtherInterfaceє default Type method(), то ви не можете просто зателефонувати SomeOtherInterface.super.method()з ChildClass. Ви можете зателефонувати лише за замовчуванням методів інтерфейсів, перелічених у пункті ChildClass's implements, а не методів їх батьківських інтерфейсів.
гвласов

1
@ Сусейка хороший момент, те саме, що немає super.super.someMethod();(тому що це було б жахливо)
Річард Тінгл

@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

Я думаю, що це найкращий приклад, який описує вищезазначене питання. Спасибі
Hemanth Peela

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
ОП говорить: "[можна] явно посилатися на реалізацію методу за замовчуванням, коли цей метод був відмінений"
dasblinkenlight
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.