web-dev-qa-db-fra.com

Implémentation d'une interface avec deux méthodes abstraites par une expression lambda

Dans Java 8 l'expression lambda est introduite pour aider à la réduction du code passe-partout . Si l'interface ne comporte qu'une seule méthode, elle fonctionne correctement. Si elle se compose de plusieurs méthodes, aucune ne fonctionne. Comment puis-je gérer plusieurs méthodes?

Nous pouvons opter pour l'exemple suivant

public interface I1()
{
    void show1();
    void show2();
}

Alors quelle sera la structure de la fonction principale pour définir les méthodes dans la principale elle-même?

28

Les expressions lambda ne sont utilisables qu'avec une interface fonctionnelle comme l'a dit Eran mais si vous avez vraiment besoin de plusieurs méthodes dans les interfaces, vous pouvez changer les modificateurs en default ou static et les remplacer dans les classes qui implémentent les si nécessaire.

public class Test {
    public static void main(String[] args) {
        I1 i1 = () -> System.out.println(); // NOT LEGAL
        I2 i2 = () -> System.out.println(); // TOTALLY LEGAL
        I3 i3 = () -> System.out.println(); // TOTALLY LEGAL
    }
}

interface I1 {
    void show1();
    void show2();
}

interface I2 {
    void show1();
    default void show2() {}
}

interface I3 {
    void show1();
    static void show2 () {}
}

Héritage

Vous ne devez pas oublier les méthodes héritées.

Ici, I2 hérite show1 et show2 et ne peut donc pas être une interface fonctionnelle.

public class Test {
    public static void main(String[] args) {
        I1 i1 = () -> System.out.println(); // NOT LEGAL BUT WE SAW IT EARLIER
        I2 i2 = () -> System.out.println(); // NOT LEGAL
    }
}

interface I1 {
    void show1();
    void show2();
}

interface I2 extends I1 {
    void show3();
}

Annotation

Pour vous assurer que votre interface est une interface fonctionnelle, vous pouvez ajouter l'annotation suivante @FunctionalInterface

@FunctionalInterface <------- COMPILATION ERROR : Invalid '@FunctionalInterface' annotation; I1 is not a functional interface
interface I1 {
    void show1();
    void show2();
}

@FunctionalInterface
interface I2 {
    void show3();
}
33
Yassin Hajaj

Les expressions lambda ne peuvent être utilisées que pour implémenter des interfaces fonctionnelles, qui sont des interfaces ayant une seule méthode abstraite. Une interface avec deux méthodes abstraites ne peut pas être implémentée par une expression lambda.

11
Eran

Je crée généralement une méthode d'usine statique directement dans l'interface:

public inteface I1 {
    void show1();
    void show2();

    public static I1 of(Runnable show1, Runnable show2) {
        return new I1() {
            void show1() { show1.run(); }
            void show2() { show2.run(); }
        };
    }
}

Usage:

I1 i1 = I1.of(() -> System.out.println("show1"), () -> System.out.println("show2"));
9
Tagir Valeev

Vous pouvez toujours utiliser la composition:

public inteface I1 {
    void show1();
    void show2();
}

public class I1Adapter {
    private final Runnable r1,r2;
    public I1Adapter(Runnable r1, Runnable r2) {this.r1=r1; this.r2=r2;}
    public void show1() {r1.run();}
    public void show2() {r2.run();}
    public static I1Adapter compose(Runnable r1, Runnable r2) {
        return new I1Adapter(r1,r2);
    }
}

Non, vous pouvez le faire (avec une importation statique):

I1 i1 = compose(()->foo(), ()->bar());
4
Tassos Bassoukos