java 抽象类的 Lambda 表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34424410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:53:08  来源:igfitidea点击:

Lambda Expressions for Abstract Classes

javalambda

提问by Halbort

I have an abstract class with one abstract method. How can I use lambda expressions to instantiate it. It cannot be made into an interface because it extends a class.

我有一个带有一个抽象方法的抽象类。我如何使用 lambda 表达式来实例化它。它不能被做成接口,因为它扩展了一个类。

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

回答by Clashsoft

You cannot directly make a lambda expression target an abstract class, as Sleiman Jneidi pointed out in his answer. However, you can use a workaround:

正如 Sleiman Jneidi 在他的回答中指出的那样,您不能直接将 lambda 表达式作为抽象类的目标。但是,您可以使用一种解决方法:

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

This can be used with a lambda expression:

这可以与 lambda 表达式一起使用:

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

In case your getSomething(...)method has arguments, use a java.util.function.Functionor the appropriate interface from the java.util.functionpackage instead of java.util.function.Supplier.

如果您的getSomething(...)方法有参数,请使用 ajava.util.function.Functionjava.util.function包中的适当接口而不是java.util.function.Supplier.



This is also how the java.lang.Threadlets you use a Runnablelambda instead of having to subclass the class:

这也是java.lang.Thread让您使用Runnablelambda 而不必对类进行子类化的方式:

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

回答by Sleiman Jneidi

No, You can't do it. Lambdas have to target single abstract method (SAM) on interfaces, and they don't work with single abstract method on abstract classes. This how it is, and you have to accept it,

不,你不能这样做。Lambda 必须针对接口上的单个抽象方法 (SAM),并且它们不适用于抽象类上的单个抽象方法。这是它的样子,你必须接受它,

Although it makes sense to have them, the language designers decided that it is not worth the complexity that will be introduced by allowing lambdas on SAM abstract classes.

尽管拥有它们是有意义的,但语言设计者认为通过在 SAM 抽象类上允许 lambda 来引入的复杂性是不值得的。

As a reference, thatswhat Brian Goetz said about allowing lambdas on SAM abstract class.

作为参考,这就是 Brian Goetz 所说的关于在 SAM 抽象类上允许 lambdas 的内容。

Main key-points from Brian's email:

布赖恩电子邮件的主要要点:

  • only 3% of the lambda candidate inner class instances had abstract classes as their target

  • Complicating the model for the sake of a few-percent-use-case seemed a bad trade

  • 只有 3% 的 lambda 候选内部类实例将抽象类作为其目标

  • 为了几个百分比的用例而使模型复杂化似乎是一个糟糕的交易

回答by Radu Simionescu

In the meantime, we now have default implementations in interfaces. I was in a similar situation, tried with an abstract class. Switched to an interface with 2 methods, one of them having a default implementation. Java identifies the interface as having a single abstract method and I can use the lambda syntax for passing implementations of the interface as arguments.

与此同时,我们现在在接口中有默认实现。我处于类似的情况,尝试使用抽象类。切换到具有 2 个方法的接口,其中一个具有默认实现。Java 将接口标识为具有单个抽象方法,我可以使用 lambda 语法将接口的实现作为参数传递。

The downside is that someone could override the method which has a default implementation if they really insist, by explicitly implementing the interface in some (anonymous or not) class. And you can't limit that because on interfaces all methods are public. Depending on your situation, that might not be a big deal.

不利的一面是,如果他们真的坚持,有人可以通过在某些(匿名或非匿名)类中显式实现接口来覆盖具有默认实现的方法。你不能限制它,因为在接口上所有方法都是公共的。根据您的情况,这可能不是什么大问题。