2013-03-01 10 views
6

Sto testando le nuove funzionalità di chiusura di Java 8; Mi chiedo perché questo pezzo di codiceJava 8 chiusure e riconoscimento del tipo

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

dà l'errore: both method z(IFA) in Test8 and method z(IFB) in Test8 match error su z invocazione del metodo run

non è il compilatore in grado di rilevare che i forceA invocazione forze x essere di tipo A e quindi la corretta z da usare è z(IFA fun)?

(una funzione simile è legale in C# utilizzando delegato; c'è un modo per ottenere lo stesso risultato in Java 8?)

+2

Se questo non viene compilato, il compilatore chiaramente non è abbastanza intelligente da capirlo. –

risposta

3

Java 8 è ancora in corso. Le ultime specifiche consentono al tuo codice di funzionare. L'implementazione del compilatore dovrebbe recuperare presto.

Tuttavia, questo tipo di sovraccarico non è un buon stile. Abbiamo firme

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

poi quando javac vede

z(arg->{ block }) 

non è evidente che z() applica. Il lavoro supplementare deve essere fatto (compilando il blocco) per sceglierne uno.

Non ci interessa davvero quanto sia difficile per javac. Il vero problema è che quando un umano vede quel codice, l'umano deve scavare più a fondo per capire a quale z() si riferisce. Non molto leggibile.

Come regola generale, evitare di sovraccaricare un metodo con interfacce funzionali della stessa origine. Diversi arietà vanno bene, non c'è nessun problema a disambiguare, per il consumo umano o javac

z(arg->{...}) 

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

Un'altra forma di sovraccarico è benedetto anche dai progettisti (Dan Smith, ecc) - stessi tipi di parametri stesso arity, ma diversi tipi restituiti

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

ma penso che sia abbastanza confuso e vorrei evitarlo.

+0

Grazie, proverò con la nuova versione del compilatore non appena verrà pubblicato. So che non è un buon stile, ma stavo solo testando le capacità linguistiche (chiusura). – Vor

0

Il corpo del lambda non viene utilizzato per determinare il tipo. Come i metodi Immagino che un riferimento al metodo possa funzionare. Ma euw, sovraccarico.