Would like to get some advise on it
My class structure is like this
public abstract class Base {}
public class Derived1 extends Base {}
public class Derived2 extends Base {}
public class ServiceClass {
public String method1(Derived1 derived1) {
return "derived1";
}
public String method2(Derived2 derived2) {
return "derived2";
}
}
In my main code (MainProg),I am trying to use the same function to refer to the 2 methods in service class and seeing the compilation error as put in the comment
public class MainProg {
public static void main(String[] args) {
ServiceClass serviceClass = new ServiceClass();
//Incompatible types: Base is not convertible to Derived1
Function<? extends Base,String> function1 = serviceClass::method1;
//Incompatible types: Object is not convertible to Derived1
Function<?,String> function2 = serviceClass::method1;
//Incompatible types: Base is not convertible to Derived2
Function<? super Base,String> function3 = serviceClass::method2;
}
}
Is there a way to declare my function object so that same function object can be used to refer to methods taking different type of arguments?
>Solution :
Yes, by using an intermediary variable:
Function<Derived1, String> function1 = serviceClass::method1;
Function<Derived2, String> function2 = serviceClass::method2;
Function<? extends Base, String> function = condition ? function1 : function2;
That said, you won’t be able to invoke function, because you don’t know whether to pass a Derived1 or a Derived2, or as the compiler puts it:
function.apply(new Derived2());
// error: The method apply(capture#1-of ? extends Base) in the type Function<capture#1-of ? extends Base,String> is not applicable for the arguments (Derived2)
You could, however, use generics to abstract over the argument type:
<T extends Base> invokeSafely(Function<T, String> function, T argument) {
function.apply(argument);
}
which would allow you to write
invokeSafely(serviceClass::method1, new Derived1());
invokeSafely(serviceClass::method2, new Derived2());
but not
invokeSafely(function, new Derived1()); // same error as before