2015-06-04 19 views
18

Ho un'interfaccia personalizzata che ho usato per un po 'di tempo che sembra qualcosa di simile:funzionale interfaccia Inheritance Quirk

public interface Function<T, R> { 
    R call(T input); 
} 

vorrei retrofit questa interfaccia sia con Java di Function così come Guava di Function , pur mantenendolo a FunctionalInterface. Pensavo di avere la perfetta organizzazione:

@FunctionalInterface 
public interface Function<T, R> extends 
     java.util.function.Function<T, R>, 
     com.google.common.base.Function<T, R> { 

    R call(T input); 

    @Override 
    default R apply(T input) { 
     return call(input); 
    } 
} 

Entrambi superinterfacce dichiarano lo stesso apply() metodo, che è stato implementato nella mia interfaccia, lasciando solo il metodo astratto call(). Stranamente, non verrà compilato, dicendomi

Annotazione "@FunctionalInterface" non valida; Funzione < T, R > non è un'interfaccia funzionale

Peggio ancora, le seguenti variazioni compilare bene:

@FunctionalInterface 
public interface Function<T, R> extends 
     java.util.function.Function<T, R> { 

    R call(T input); 

    @Override 
    default R apply(T input) { 
     return call(input); 
    } 
} 

@FunctionalInterface 
public interface Function<T, R> extends 
     com.google.common.base.Function<T, R> { 

    R call(T input); 

    @Override 
    default R apply(T input) { 
     return call(input); 
    } 
} 

public interface Function<T, R> extends 
     java.util.function.Function<T, R>, 
     com.google.common.base.Function<T, R> { 

    R call(T input); 

    @Override 
    default R apply(T input) { 
     return call(input); 
    } 
} 

@FunctionalInterface 
public interface Function<T, R> extends 
     java.util.function.Function<T, R>, 
     com.google.common.base.Function<T, R> { 

    @Override 
    R apply(T input); 
} 

C'è un motivo per cui la prima versione non verrà compilata?

+1

tuo terzo compila perché non si è aggiunto il vincolo che deve essere un '@ FunctionalInterface' (che è un'annotazione convalidato dal compilatore). –

+1

@SotiriosDelimanolis, ovviamente. – shmosel

+5

Stai compilando con Eclipse? Compilano bene con il compilatore di Oracle. –

risposta

9

Come indicato nei commenti, si compila bene con il compilatore oracle. È un bug di eclissi.

In attesa di una correzione di bug, personalmente io rimuovere l'annotazione @FunctionalInterface (il 3 ° variante):

public interface Function<T, R> 
           extends 
            java.util.function.Function<T, R>, 
            com.google.common.base.Function<T, R> { 

    R call(T input); 

    @Override 
    default R apply(T input) { 
     return call(input); 
    } 
} 

Il principale inconveniente di questa soluzione è che il compilatore bug eclisse impedisce di utilizzare il Function come lambda target type .


Se davvero si vuole mantenere @FunctionalInterface sul Function, un (brutto) soluzione potrebbe essere quella di introdurre un interfaccia intermedia:

public interface AdapterFunction<T, R> 
             extends 
              java.util.function.Function<T, R>, 
              com.google.common.base.Function<T, R> { 
    @Override 
    default R apply(T input) { 
     return null; 
    } 
} 

e lasciate che il vostro Function estende questo AdapterFunction:

@FunctionalInterface 
public interface Function<T, R> 
           extends 
            AdapterFunction<T, R> { 

    R call(T input); 

    @Override 
    default R apply(T input) { 
     return call(input); 
    } 
} 

In questo caso, lo Function è un tipo di destinazione valido anche per eclissi :

Function<String, Object> function = st -> st.toString(); 
+1

Sì, ho trovato una segnalazione di bug simile [qui] (https://bugs.eclipse.org/bugs/show_bug.cgi?id=453552). Non mi interessa l'annotazione stessa; il problema è che non mi permetterà di usare espressioni lambda. Ho provato qualcosa di simile all'idea dell'adattatore, senza successo. Ci riproverò domani. – shmosel

+1

Anche la soluzione con 'AdapterFunction' funziona in eclissi. Ma la rimozione di '@ FunctionalInterface' (terza variante) non è – gontard

+0

Hai ragione, funziona implementa' apply() 'nell'adattatore. Grazie! – shmosel