2016-05-03 20 views
6

Ho un'interfaccia funzionale che estende la funzione standard jdk semplicemente ai tipi generici. Ora voglio combinare due funzioni che utilizzano andthen che sta gettando errore del compilatoreJava 8 estendere l'interfaccia di funzione e combinarli

Error:(25, 25) java: method andThen in interface java.util.function.Function<T,R> cannot be applied to given types;
required: java.util.function.Function<? super ui.instrumentation.api.messaging.Message<R>,? extends V> found: ui.instrumentation.api.transformation.Transformer<T,R> reason: cannot infer type-variable(s) V (argument mismatch; ui.instrumentation.api.transformation.Transformer<T,R> cannot be converted to java.util.function.Function<? super ui.instrumentation.api.messaging.Message<R>,? extends V>)

Ecco il codice di esempio:

public interface Transformer<T,R> extends Function<Message<T>, Message<R>> { 

    static <T, R> Transformer<T, R> combine2(Transformer<T, R> first, Transformer<T, R> second) { 
     return first.andThen(second)); 
    } 
} 

C'è un modo per combinare le funzioni che si estende interfaccia funzione standard o c'è meglio modo di fare questo?

+2

Perché proprio avete bisogno la funzione di 'combine2', quando' andThen' fa letteralmente la stessa cosa, per il tipo di argomento più generale 'Function'? – Mshnik

+0

Quindi vuoi una funzione che richiede un 'Messaggio ', passa a 'prima', ottiene un' Messaggio ' indietro, quindi in qualche modo passa 'Messaggio ' a' second' anche se 'second' ha bisogno di un' Messaggio 'non un' messaggio '. – immibis

+2

La mia raccomandazione: non utilizzare tali interfacce estensioni. Si risparmiano alcune lettere da digitare a scapito di non consentire l'uso delle implementazioni esistenti dell'interfaccia di base (qui 'Funzione'). Quindi, è necessario ri-implementare tutto, non solo "e poi", anche le funzioni banali come 'Function.identity()' non possono essere usate come 'Transformer'. Impara la lezione dagli errori dell'altro; pur avendo la stessa firma funzionale, non puoi usare un 'Transformer ', dove è richiesto 'UnaryOperator >' (un altro esempio di non consentire il tipo di base 'Function') ... – Holger

risposta

5

È necessario sia risolvere i vostri farmaci generici, e invece di usare andThen, che sarebbe tornato solo Function, si sarà meglio inlining lambda da soli:

static <T1, T2, T3> Transformer<T1, T3> combine2(Transformer<T1, T2> first, Transformer<T2, T3> second) { 
    return (Message<T1> input) -> second.apply(first.apply(input)); 
} 
5

Il primo problema è che andThen prende il valore di ritorno di una funzione e rende il tipo di parametro della funzione successiva, quindi è necessario, come spiegato da @LouisWasserman, concatenarli end-to-end con il tipo di output di uno corrispondente al tipo di input del successivo:

static <T1, T2, T3> Transformer<T1, T3> combine2(Transformer<T1, T2> first, Transformer<T2, T3> second) { 

Il secondo problema, come spiega anche, è che Function.andThen, che si sta chiamando, restituisce un Function, non uno Transformer. Notare, tuttavia, che Function e Transformer hanno la stessa forma: input singolo, uscita singola. A causa di ciò, è possibile utilizzare uno e poi adattarlo ad un altro con un riferimento metodo come questo:

static <T1, T2, T3> Transformer<T1, T3> combine(Transformer<T1, T2> first, Transformer<T2, T3> second) { 
    return first.andThen(second)::apply; 
} 

Non è necessario creare una funzione per fare questo. È possibile utilizzare la stessa tecnica chiamando direttamente Function.andThen():

Transformer<String,Integer> t1 = ... 
    Transformer<Integer,Double> t2 = ... 
    Transformer<Double,String> t3 = ... 

    Transformer<String,String> t123 = t1.andThen(t2).andThen(t3)::apply; 
+0

Grazie a @HankD e @LouisWasserman, che mi ha aiutato a capire meglio Il mio obiettivo originale è quello di combinare una lista di molte funzioni (trasformatori in es. Case) concatenandole con eThen. Senti Ho davvero bisogno di sovrascrivere il metodo di combinare per ogni ulteriore trasformatore come questo 'static Transformer combinare (Transformer prima, Transformer secondo, Transformer terzo) { ritorno first.andThen (secondo) .andThen (terzo) :: applicare; } ' C'è un modo migliore per farlo in modo più generico combinare l'elenco delle funzioni? – Raja

+1

Ho aggiornato la mia risposta per mostrare come potresti farlo –