Lambda Expressions for Abstract Classes

后端 未结 3 1438
梦如初夏
梦如初夏 2020-11-30 03:03

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.

相关标签:
3条回答
  • 2020-11-30 03:42

    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:

    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:

    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.Function or the appropriate interface from the java.util.function package instead of java.util.function.Supplier.


    This is also how the java.lang.Thread lets you use a Runnable lambda instead of having to subclass the class:

    Thread t = new Thread(() -> System.out.println("Hello World"));
    t.start();
    
    0 讨论(0)
  • 2020-11-30 03:57

    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,

    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.

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

    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

    0 讨论(0)
  • 2020-11-30 03:58

    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.

    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.

    0 讨论(0)
提交回复
热议问题