Как вызвать реализацию интерфейса метода по умолчанию в переопределяющей реализации?

Предположим, у меня есть следующий код:

interface HumanoidForm {
    default HumanoidForm reproduce() {
        <appropriate code for humanoid form reproduction>
    }
}

class Android extends Machine implements HumanoidForm {
    public HumanoidForm reproduce() {
        <appropriate code for android reproduction> // how to use HumanoidForm's default implementation here?
    }
}

Теперь предположим, что "соответствующий код для воспроизведения андроида" лучше всего описывается с использованием "соответствующего кода для воспроизведения гуманоидной формы" в качестве подпрограммы. Как я могу получить доступ к "соответствующему коду для гуманоидной формы" из "соответствующего кода для воспроизведения Android"? Я могу придумать три способа, но ни один из них не работает:

  • Простой вызов repce() вызывает реализацию с переопределением.
  • Запись ((HumanoidForm) this).reproduce() по-прежнему вызывает переопределяющую реализацию.
  • Подражая повторному использованию реализаций методов в суперклассах путем переопределения методов, можно подумать о написании super.reproduce(). Тем не менее, это относится к реализации воспроизведения машины, которая может даже не существовать.

Таким образом, кажется, нет способа повторно использовать код в методе по умолчанию для переопределения. Это действительно так?

4 ответа

Решение

На самом деле, вы можете свободно выбирать существующую реализацию. Позвольте мне дать вам сценарий, немного более сложный, чем ваш. Что еще хуже, все A,B & C имеет такую ​​же сигнатуру метода.

interface A {
    default void doWork() {
       System.out.println("Default implementation From A");
    }
}

interface B{
    default void doWork() {
      System.out.println("Default implementation From B");  
    }   
}

class C{
    void doWork(){
        System.out.println("Default implementation From C");
    }       
}

Теперь я создаю подкласс для C, который реализует A & B:

class Tester extends C implements A, B
{
    @Override public void doWork(){
        A.super.doWork();  //Invoke A's implementation
        B.super.doWork();  //Invoke B's implementation
        super.doWork();    //Invoke C's implementation
    }
}

Выход будет:

Default implementation From A
Default implementation From B
Default implementation From C

когда вы бежите:

new Tester().doWork();
HumanoidForm.super.reproduce();

Взгляните на это: https://blog.idrsolutions.com/2015/01/java-8-default-methods-explained-5-minutes/

В частности, в разделе, где говорится:"Если мы хотим специально вызвать один из методов sayHi () в InterfaceA или InterfaceB, мы также можем сделать следующее:"

public class MyClass implements InterfaceA, InterfaceB {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    // TODO code application logic here
}

@Override
public void saySomething() {
    System.out.println("Hello World");
}

@Override
public void sayHi() {
   InterfaceA.super.sayHi();
}

}

interface InterfaceA {

public void saySomething();

default public void sayHi() {
    System.out.println("Hi from InterfaceA");
}

}

interface InterfaceB {
 default public void sayHi() {
    System.out.println("Hi from InterfaceB");
}
}

Таким образом, кажется, нет способа повторно использовать код в методе по умолчанию для переопределения. Это действительно так?

Нет, вы можете повторно использовать код. Вы можете легко проверить это, и вы увидите, что следующий код работает:

public class Test implements HumanoidForm
{             
    public static void main(String[] args) 
    {       
        new Test().reproduce();         
    }   

    @Override
    public void reproduce(){
        HumanoidForm.super.reproduce();  //Invoking default method
        System.out.println("From implementing class");
    }       
}

interface HumanoidForm {
    default void reproduce() {
       System.out.println("From default interface");
    }
}

ВЫХОД:

From default interface
From implementing class
Другие вопросы по тегам