web-dev-qa-db-fra.com

Appel explicite d'une méthode par défaut dans Java

Java 8 introduit méthodes par défaut pour permettre d'étendre les interfaces sans avoir à modifier les implémentations existantes.

Je me demande s'il est possible d'appeler explicitement l'implémentation par défaut d'une méthode lorsque cette méthode a été remplacée ou n'est pas disponible en raison d'implémentations par défaut en conflit dans différentes 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?
    }
}

En considérant le code ci-dessus, comment appelleriez-vous A.foo() à partir d'une méthode de classe B?

207
GOTO 0

Selon cet article vous accédez à la méthode par défaut dans l'interface A en utilisant

A.super.foo();

Cela pourrait être utilisé comme suit (en supposant que les interfaces A et C ont toutes deux des méthodes par défaut 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 et C peuvent utiliser une méthode .foo() et leur implémentation par défaut peut être choisie ou vous pouvez en utiliser une (ou les deux) dans le cadre de votre nouvelle méthode foo(). Vous pouvez également utiliser la même syntaxe pour accéder aux versions par défaut d'autres méthodes de votre classe d'implémentation.

La description formelle de la syntaxe d'invocation de méthode se trouve dans le chapitre 15 du JLS .

269
Richard Tingle

Le code ci-dessous devrait fonctionner.

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

Sortie:

B.foo
A.foo
14
Abhijith Nagarajan

Cette réponse est écrite principalement pour les utilisateurs qui viennent de la question 4504755 qui est fermée.

Les interfaces Java 8 introduisent certains aspects de l'héritage multiple. Les méthodes par défaut ont un corps de fonction implémenté. Pour appeler une méthode de la super-classe, vous pouvez utiliser le mot-clé super, mais si vous souhaitez le créer avec une super-interface, vous devez le nommer explicitement.

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

Sortie:

Bonjour ParentClass!
Bonjour InterfaceFoo!
Bonjour InterfaceBar!

7
Dávid Horváth

Vous n'avez pas besoin de remplacer la méthode par défaut d'une interface. Appelez-le comme suit:

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

Sortie:

A.foo

3
Masudul