2015-12-22 21 views
18

Ho una classe astratta con un metodo astratto. Come posso usare espressioni lambda per istanziarlo. Non può essere trasformato in un'interfaccia perché estende una classe.Espressioni lambda per classi astratte

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 questo tipo di situazioni sarebbe utile includere una [MCVE] (http://stackoverflow.com/help/mcve), dove si dispone di una certa classe super, la classe astratta e un insta che vuoi ridurre ad un'espressione lambda – luk2302

+0

Mostrare qualche codice? – Jan

+0

Perché non è possibile creare un'interfaccia per getSomething() e fare in modo che la classe astratta estenda Concrete e implementa l'interfaccia? – Jan

risposta

30

Non è possibile eseguire direttamente un'espressione lambda come classe astratta, come indicato da Sleiman Jneidi nella sua risposta. Tuttavia, è possibile introdurre una soluzione:

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

Questo può essere usato con un'espressione lambda:

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

Si potrebbe anche aver notato che questo è come la classe java.lang.Thread vuol sostenere Runnables out- of-the-box:

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

Grazie mille. L'ho fatto. Funziona perfettamente. – Halbort

+0

Semplice e pulito :) –

+0

Non sono d'accordo che Thread sia definito in modo simile. Un Runnable come argomento del costruttore su Thread è naturale e Runnable simple FunctionalInterface. Non sembra simile a questa soluzione alternativa. – snap

18

No, non si può farlo. Lambdas deve indirizzare un singolo metodo astratto sulle interfacce e non funzionano con un singolo metodo astratto su classi astratte. Così com'è, e devi accettarlo,

Sebbene abbia senso averli, i progettisti di linguaggi hanno deciso che non vale la complessità che verrà introdotta consentendo lambda sulle classi astratte SAM.

As a reference, thats quello che Brian Goetz ha detto riguardo l'autorizzazione di lambda sulla classe astratta SAM.

principali punti chiave da e-mail di Brian:

  • solo il 3% del candidato lambda istanze di classi interne avevano classi astratte come loro obiettivo

  • A complicare il modello per il l'uso di un caso d'uso a poche percentuali sembrava un cattivo affare