Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Using wildcard with Generic method

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading