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

247

Java 8 présente des méthodes par défaut pour offrir la possibilité d'étendre les interfaces sans avoir à modifier les implémentations existantes.

Je me demande s'il est possible d'invoquer 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 conflictuelles 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?
    }
}

Compte tenu du code ci-dessus, comment appelleriez-vous à A.foo()partir d'une méthode de classe B?

GOTO 0
la source
Pouvez-vous me dire pourquoi vous avez implémenté votre méthode foo () dans votre interface A ??.
Maciej Cygan
20
@MaciejCygan C'est autorisé dans Java 8
Rohit Jain

Réponses:

330

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

A.super.foo();

Cela pourrait être utilisé comme suit (en supposant que les interfaces Aet les Cdeux ont 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
    }
}

Aet Cpeuvent tous deux avoir des .foo()méthodes et l'implémentation par défaut spécifique peut être choisie ou vous pouvez en utiliser une (ou les deux) dans le cadre de votre nouvellefoo() méthode. Vous pouvez également utiliser la même syntaxe pour accéder aux versions par défaut dans d'autres méthodes de votre classe d'implémentation.

Une description formelle de la syntaxe d'appel de méthode peut être trouvée dans le chapitre 15 du JLS .

Richard Tingle
la source
14
Notez également que si A extends SomeOtherInterface, et SomeOtherInterfacesatisfaira default Type method(), alors vous ne pouvez pas appeler SomeOtherInterface.super.method()de ChildClass. Vous ne pouvez appeler que les méthodes par défaut des interfaces énumérées dans la clause ChildClass's implements, pas les méthodes de leurs interfaces parentes.
gvlasov
1
@Suseika bon point, le même qu'il n'y en a pas super.super.someMethod();(car ce serait horrible)
Richard Tingle
@gvlasov bon point, mais comment accéder à la méthode par défaut d'une interface parent à partir d'une interface enfant, est-ce possible ?? Mise à jour .......... Oui Possible, l'explication la plus concrète ici stackoverflow.com/a/24280376/3791156
Raaghu
@RichardTingle réponse sans faille!
gaurav
17

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

Production:

B.foo
A.foo
Abhijith Nagarajan
la source
Je pense que c'est le meilleur exemple qui décrit la question ci-dessus. Merci
Hemanth Peela
8

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

Les interfaces Java 8 présentent 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 à partir de la super classe, vous pouvez utiliser le mot-clé super, mais si vous voulez faire cela 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();
    }
}

Production:

Bonjour ParentClass!
Bonjour InterfaceFoo!
Bonjour InterfaceBar!

Dávid Horváth
la source
3

Vous n'avez pas besoin de remplacer la méthode par défaut d'une interface. Appelez-le simplement 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();
    }
}

Production:

A.foo

Masudul
la source
9
OP dit: "[est-il] possible d'invoquer explicitement l'implémentation par défaut d'une méthode lorsque cette méthode a été remplacée"
dasblinkenlight