2015-12-22 10 views
18

Ich habe eine abstrakte Klasse mit einer abstrakten Methode. Wie kann ich Lambda-Ausdrücke zur Instanziierung verwenden? Es kann nicht zu einer Schnittstelle gemacht werden, weil es eine Klasse erweitert. KeinLambda-Ausdrücke für abstrakte Klassen

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

in dieser Art von Situationen wäre es hilfreich, eine [MCVE] enthalten (http://stackoverflow.com/help/mcve), wo Sie einige super Klasse, die abstrakte Klasse und ein Insta Einstellung, die Sie auf einen Lambda-Ausdruck reduziert haben möchten – luk2302

+0

Code anzeigen? – Jan

+0

Warum können Sie keine Schnittstelle für getSomething() erstellen und Ihre abstrakte Klasse Concrete erweitern und Interface implementieren? – Jan

Antwort

30

Sie können ein Lambda-Expressionsziel nicht direkt zu einer abstrakten Klasse machen, wie Sleiman Jneidi in seiner Antwort darauf hingewiesen hat. Sie können jedoch eine Abhilfe vorstellen:

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

Dies kann mit einem Lambda-Ausdruck verwendet werden:

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

Sie auch bemerkt haben könnte, dass dies, wie die java.lang.Thread Klasse macht es Runnables out- zu unterstützen of-the-box:

Thread t = new Thread(() -> System.out.println("Hello World")); 
t.start(); // eventually prints 'Hello World' 
+0

Vielen Dank. Ich hab's gemacht. Es funktioniert perfekt. – Halbort

+0

Einfach und sauber :) –

+0

Ich bin nicht damit einverstanden, dass Thread in ähnlicher Weise definiert ist. Ein Runnable als Konstruktorargument zu Thread ist ein natürliches und ausführbares einfaches FunctionalInterface. Es sieht nicht ähnlich dieser Problemumgehung aus. – snap

18

, Sie können es nicht tun. Lambdas müssen einzelne abstrakte Methoden auf Interfaces anwenden, und sie arbeiten nicht mit einzelnen abstrakten Methoden für abstrakte Klassen. Wie es ist, und Sie müssen es akzeptieren,

Obwohl es sinnvoll ist, sie zu haben, entschieden die Sprachdesigner, dass es nicht die Komplexität wert ist, die eingeführt wird, indem Lambdas auf SAM abstrakten Klassen erlaubt wird.

As a reference, thats was Brian Goetz über das Zulassen von Lambdas auf der abstrakten SAM-Klasse sagte.

Hauptschlüssel-Punkte von Brian E-Mail:

  • nur 3% des Lambda-Kandidaten innere Klasseninstanzen als Ziel abstrakte Klassen hatten

  • das Modell für die Erschwerend Im Hinblick auf ein paar Prozent-Use-Case schien ein schlechter Handel

Verwandte Themen