2015-12-22 14 views
18

Mam klasę abstrakcyjną z jedną abstrakcyjną metodą. Jak używać wyrażeń lambda do tworzenia instancji. Nie można go przekształcić w interfejs, ponieważ rozszerza klasę.Wyrażenia Lambda dla klas abstrakcyjnych

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

w tego rodzaju sytuacjach pomocne byłoby dołączenie [MCVE] (http://stackoverflow.com/help/mcve) gdzie znajduje się super klasa, klasa abstrakcyjna i insta oznaczenie, które chciałbyś ograniczyć do wyrażenia lambda. – luk2302

+0

Pokaż kod? – Jan

+0

Dlaczego nie można utworzyć interfejsu dla funkcji getSomething() i rozszerzyć swoją klasę abstrakcji na interfejs Concrete i implementować interfejs? – Jan

Odpowiedz

30

Nie możesz bezpośrednio uczynić z celu ekspresji lambda klasy abstrakcyjnej, jak zauważył Sleiman Jneidi w swojej odpowiedzi. Można jednak wprowadzić rozwiązania:

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

ten może być używany z wyrażenia lambda:

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

Warto również zauważyć, że jest to jak klasa java.lang.Thread to wspierać Runnables uliczne of-the-box:

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

Dziękuję bardzo. Ja to zrobiłem. Działa idealnie. – Halbort

+0

Prosty i schludny :) –

+0

Nie zgadzam się, że wątek jest zdefiniowany w podobny sposób. Runnable jako argument konstruktora Thread jest naturalny i Runnable simple FunctionalInterface. Nie wygląda to podobnie do tego obejścia. – snap

18

Nie, nie można zrobić to. Lambdas musi kierować pojedynczą abstrakcyjną metodę na interfejsy i nie działa z pojedynczą abstrakcyjną metodą na abstrakcyjnych klasach. Tak to jest i musisz to zaakceptować, chociaż ma sens, aby je mieć, projektanci języka zdecydowali, że nie jest to warte złożoności, która zostanie wprowadzona przez zezwolenie na lambdas na klasach abstrakcyjnych SAM.

As a reference, thats co Brian Goetz powiedział o zezwoleniu na lambdas w klasie abstrakcyjnej SAM.

Główne kluczowe punkty z email Briana:

  • tylko 3% kandydata lambda wewnętrzne przypadki klasa miała klasy abstrakcyjne jako cel

  • komplikuje model dla ze względu na kilka-procentowy przypadek użycia wydawał się złym handlem

Powiązane problemy