I have a functional interface that extends standard jdk function to simply the generic types. Now I want to combine two functions using andThen which is throwing compiler error
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 tojava.util.function.Function<? super ui.instrumentation.api.messaging.Message<R>,? extends V>
)
Here is the sample code:
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));
}
}
Is there a way to combine functions that extends standard Function interface or is there better way to do this?
You need to both fix your generics, and instead of using andThen
, which would only return a Function
, you'll be better off inlining the lambda yourself:
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));
}
The first problem is that andThen
takes the return value of one function and makes that the parameter type of the next function, so you need, as @LouisWasserman explains, to chain them end-to-end with the output type of one matching the input type of the next:
static <T1, T2, T3> Transformer<T1, T3> combine2(Transformer<T1, T2> first, Transformer<T2, T3> second) {
The second problem, as he also explains, is that Function.andThen
, which you are calling, returns a Function
, not a Transformer
. Note, however, that Function
and Transformer
have the same shape -- single input, single output. Because of that, you can use one and then adapt it to the other with a method reference like this:
static <T1, T2, T3> Transformer<T1, T3> combine(Transformer<T1, T2> first, Transformer<T2, T3> second) {
return first.andThen(second)::apply;
}
You don't need to create a function to do this. You can use the same technique calling Function.andThen()
directly:
Transformer<String,Integer> t1 = ...
Transformer<Integer,Double> t2 = ...
Transformer<Double,String> t3 = ...
Transformer<String,String> t123 = t1.andThen(t2).andThen(t3)::apply;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With