Llamar explícitamente a un método predeterminado en Java


Java 8 introduce métodos predeterminados para proporcionar la capacidad de extender interfaces sin la necesidad de modificar implementaciones existentes.

Me pregunto si es posible invocar explícitamente la implementación predeterminada de un método cuando ese método ha sido sobrescrito o no está disponible debido a implementaciones predeterminadas conflictivas en diferentes interfaces.

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

Considerando el código anterior, ¿cómo llamarías a A.foo() desde un método de clase B?

Author: Richard Tingle, 2013-11-14

4 answers

Según este artículo usted accede al método predeterminado en interfaz A usando

A.super.foo();

Esto podría usarse de la siguiente manera (suponiendo que las interfaces A y C tienen métodos predeterminados 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 y C puede tener ambos métodos .foo() y se puede elegir la implementación predeterminada específica o puede usar uno (o ambos) como parte de su nuevo método foo(). También puede utilizar la misma sintaxis para acceder a las versiones predeterminadas de otros métodos de la implementación clase.

La descripción formal de la sintaxis de invocación del método se puede encontrar en el capítulo 15 de la JLS.

 203
Author: Richard Tingle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-10 23:20:52

El siguiente código debería funcionar.

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

Salida:

B.foo
A.foo
 11
Author: Abhijith Nagarajan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-14 14:01:49

No es necesario anular el método predeterminado de una interfaz. Simplemente llámelo de la siguiente manera:

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

Salida:

A. foo

 3
Author: Masudul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-14 13:37:47

Esta respuesta está escrita principalmente para usuarios que vienen de la pregunta 45047550 que está cerrado.

Las interfaces Java 8 introducen algunos aspectos de la herencia múltiple. Los métodos predeterminados tienen un cuerpo de función implementado. Para llamar a un método desde la superclase puedes usar la palabra clave super, pero si quieres hacer esto con una super interfaz es necesario nombrarlo explícitamente.

class Clazz {

    public void foo() {
        System.out.println("Hello Clazz!");
    }

}

interface Interface111 {

    default public void foo() {
        System.out.println("Hello Interface111!");
    }

}

interface Interface222 {

    default public void foo() {
        System.out.println("Hello Interface222!");
    }

}

public class Example extends Clazz implements Interface111, Interface222 {

    public void foo() {
        super.foo(); // (note: Clazz.super is wrong!)
        Interface111.super.foo();
        Interface222.super.foo();
    }

    public static void main(String[] args) {
        new Example().foo();
    }

}

Salida:

Hola Clazz!
Hola Interface111!
Hola Interface222!

 2
Author: Dávid Horváth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-20 17:49:50