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

В Java 8 введено лямбда-выражение, чтобы помочь с сокращением кода шаблона. Если интерфейс имеет только один метод, он работает нормально. Если он состоит из нескольких методов, то ни один из методов не работает. Как я могу обрабатывать несколько методов?

Мы можем перейти к следующему примеру

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

Тогда какова будет структура основной функции для определения методов в самой себе?

Ответ 1

Лямбда-выражения применимы только к функциональному интерфейсу, как говорит Эран, но если вам действительно нужны несколько методов в интерфейсах, вы можете изменить модификаторы на default по default или static и переопределить их в классах, которые их реализуют, если это необходимо.

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

наследование

Вы не должны забывать унаследованные методы.

Здесь I2 наследует show1 и show2 и, следовательно, не может быть функциональным интерфейсом.

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

аннотирование

Чтобы убедиться, что ваш интерфейс является функциональным интерфейсом, вы можете добавить следующую аннотацию @FunctionalInterface

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

@FunctionalInterface
interface I2 {
    void show3();
}

Ответ 2

Лямбда-выражения могут использоваться только для реализации функциональных интерфейсов, которые представляют собой интерфейсы, имеющие один абстрактный метод. Интерфейс с двумя абстрактными методами не может быть реализован с помощью лямбда-выражения.

Ответ 3

Обычно я создаю статический метод factory непосредственно в интерфейсе:

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

Использование:

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

Ответ 4

Вы всегда можете использовать композицию:

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

Нет, вы можете сделать (со статическим импортом):

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