2013-03-01 12 views
6

Testuję nowe funkcje zamykania Java 8; Zastanawiam się, dlaczego ten kawałek koduZamknięcia Java 8 i rozpoznawanie typów

public class Test8 { 
    private class A { int a;} 
    private class B { int b;}  
    interface IFA { void ifa(A param); } 
    interface IFB { void ifb(B param); } 
    private void forceA(A expr) { }  
    private void z(IFA fun) { System.out.println("A"); fun.ifa(new A()); } 
    private void z(IFB fun) { System.out.println("B"); fun.ifb(new B()); }  

    public void run() { 
     z(x -> forceA(x)); 
    } 
    public static void main(String args[]) { new Test8().run(); } 
} 

daje błąd: both method z(IFA) in Test8 and method z(IFB) in Test8 match error w systemie z wezwaniem w metodzie run

nie jest kompilator stanie wykryć, że forceA inwokacja zmusza x być typu A, a zatem prawidłowe użycie to z(IFA fun)?

(podobna funkcja jest legalne w C# przy użyciu delegata; czy istnieje sposób, aby uzyskać ten sam rezultat w Java 8?)

+2

Jeśli to nie zostanie skompilowane, kompilator wyraźnie nie jest wystarczająco inteligentny, aby to zrozumieć. –

Odpowiedz

3

Java 8 jest nadal w toku. Najnowsza specyfikacja umożliwia działanie twojego kodu. Wdrożenie kompilatora powinno wkrótce nadejść.

Jednak ten rodzaj przeciążenia nie jest dobrym stylem. Mamy podpisy

z(A->void) 
    z(B->void) 

wtedy gdy javac widzi

z(arg->{ block }) 

to nie jest oczywiste, które stosuje z(). Aby wybrać jedną, należy wykonać dodatkową pracę (poprzez kompilację bloku).

Nie przejmujemy się tym, jak trudno jest uzyskać javac. Prawdziwym problemem jest to, że kiedy człowiek widzi ten kod, człowiek musi głębiej sięgnąć, aby zrozumieć, do którego odnosi się. Niezbyt czytelne.

Jako ogólną zasadę, należy unikać przeciążania metody z funkcjonalnymi interfejsami o tej samej arytmetyce. Różne arities są w porządku, nie ma problemu, aby disambiguate, dla ludzi lub javac

z(arg->{...}) 

    z((arg1,arg2)->{...}) 

Inną formą przeciążenia jest również poświęcony przez projektantów (Dan Smith etc) - samej budowie, samych typów parametrów, ale różne rodzaje powrotne

z(X->R1) 
    z(X->R2) 

ale myślę, że to też jest bardzo mylące i uniknęłbym tego.

+0

Dzięki, spróbuję z nową wersją kompilatora, gdy tylko zostanie opublikowana. Wiem, że to nie jest dobry styl, ale testowałem tylko możliwości językowe (zamknięcie). – Vor

0

Ciało lambda nie jest używany do określenia jego typu. Podobnie jak metody. Przypuszczam, że odwołanie do metody może działać. Ale euw, przeciążenie.