Лямбда-выражения для абстрактных классов

У меня есть абстрактный класс с одним абстрактным методом. Как я могу использовать лямбда-выражения для его создания. Он не может быть превращен в интерфейс, потому что он расширяет класс.

public class Concrete<T> {
    // Has a bunch of predefined methods.
}


public abstract class Abstract<T> extends Concrete<T> {
    public T getSomething();
    // Uses inherited methods from Concrete class
}

public class Driver {
    public static void main(String[] args) {
        System.out.println(new Abstract<String>() {
            public String getSomething() {
                // Returns something using inherited methods from Abstract              
                // Class and Concrete Class
            }
        });
    }
}

Ответы

Ответ 1

Вы не можете напрямую сделать лямбда-выражение целевым для абстрактного класса, как указал Слейман Джнейди в своем ответе. Однако вы можете использовать обходной путь:

public class AbstractLambda<T> extends Abstract<T>
{
    private final Supplier<? extends T> supplier;
    public AbstractLambda(Supplier<? extends T> supplier)
    {
        this.supplier = supplier;
    }

    @Override
    public T getSomething()
    {
        return this.supplier.get();
    }
}

Это можно использовать с лямбда-выражением:

Abstract<String> a = new AbstractLambda<>(() -> "Hello World");
System.out.println(a.getSomething()); // prints 'Hello World'

В случае, если ваш getSomething(...) имеет аргументы, используйте java.util.function.Function или соответствующий интерфейс из пакета java.util.function вместо java.util.function.Supplier.


Это также то, как java.lang.Thread позволяет использовать лямбду Runnable вместо того, чтобы создавать подкласс класса:

Thread t = new Thread(() -> System.out.println("Hello World"));
t.start();

Ответ 2

Нет, вы не можете сделать это. Lambdas должен ориентироваться на один абстрактный метод на интерфейсах, и они не работают с одним абстрактным методом для абстрактных классов. Это как это, и вы должны принять его,

Несмотря на то, что имеет смысл иметь их, разработчики языка решили, что это не стоит сложность, которая будет введена, разрешив лямбда на абстрактных классах SAM.

Как ссылка, thats, что сказал Брайан Гетц о разрешении лямбда в абстрактном классе SAM.

Основные ключевые моменты из письма Брайана:

  • только 3% кандидата лямбды внутренние экземпляры класса имели абстрактные классы в качестве своей цели

  • Усложнение модели для ради использования в нескольких процентах случаев было плохой сделкой