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