mercredi 24 juin 2020

Calling suit method based on parameter type (when parameter is general or specific)

How to call method with specific type instead of general type if I have two methods?

I prepared two examples: simple and extended.


Simple example:

public class Testing {

    static void process(Object object) {
        System.out.println("process Object");
    }

    static void process(Integer integer) {
        System.out.println("process Integer");
    }

    public static void main(String[] args) {
        Object objectString = new String("a");
        Object objectInteger = new Integer(1);

        process(objectString); // "process Object"
        process(objectInteger); // it prints "process Object" instead of "process Integer"
    }
}

I know I can create reference with specific type:

Integer objectInteger = new Integer(1);

and suit method will be called.

But I want to use general type (it's good practice to do List<String> list = new ArrayList<>() instead of ArrayList<String> list = new ArrayList<>()).


Extended example:

public class Testing {

    interface MyInterface {
    }
    static class First implements MyInterface {
        String first = "first";
    }
    static class Second implements MyInterface {
        String second = "second";
    }
    static class SpecificSecond extends Second {
        String specificSecond = "specificSecond";
    }

    public static void process(MyInterface myInterface) {
        if (myInterface instanceof First) {
            System.out.println("General case: " + ((First) myInterface).first);
        } else if (myInterface instanceof Second) {
            System.out.println("General case: " + ((Second) myInterface).second);
        } else {
            System.out.println("Should not call");
        }
    }

    public static void process(SpecificSecond specificSecond) {
        System.out.println("Specific case for SpecificSecond: " + specificSecond.specificSecond);
    }

    public static void main(String[] args) {
        MyInterface first = new First();
        MyInterface second = new Second();
        MyInterface specificSecond = new SpecificSecond();

        Testing.process(first); // "General case: first"
        Testing.process(second); // "General case: second"
        Testing.process(specificSecond); // it prints "General case: second" instead of "Specific case for SpecificSecond: specificSecond"
    }
}

I know I can do:

SpecificSecond specificSecond = new SpecificSecond();

but without using my interface I can't use my other generic methods and classes.

How can I change methods process (but without changing contract) to call proper method?

I found workaround (create new proxy method for choosing proper method and change name of general method):

public static void process(MyInterface myInterface) {
    if (myInterface instanceof SpecificSecond) {
        process((SpecificSecond) myInterface);
    } else {
        processGeneral(myInterface);
    }
}

private static void processGeneral(MyInterface myInterface) {
    if (myInterface instanceof First) {
        System.out.println("General case: " + ((First) myInterface).first);
    } else if (myInterface instanceof Second) {
        System.out.println("General case: " + ((Second) myInterface).second);
    } else {
        System.out.println("Should not call");
    }
}

private  static void process(SpecificSecond specificSecond) {
    System.out.println("Specific case for SpecificSecond: " + specificSecond.specificSecond);
}

But with this I can't find all uses of specific process(SpecificSecond) method (because they all pass through proxy method) in my IDE.

Is there any other workaround to enforce calling process(SpecificSecond) method?

How can I design it better?

Aucun commentaire:

Enregistrer un commentaire