2

Let's say we have these code:

class Parent {}

class Child1 extends Parent {}

class Child2 extends Parent {}

class Main {
    static void method(Parent obj) {}
    static void method(Child1 obj) {}
    static void method(Child2 obj) {}
    public static void main(String[] arg) {
        Parent obj1 = new Child1();
        Parent obj2 = new Child2();
        method(obj1); //call method(Child1 obj)
        method(obj2); //call method(Child2 obj)
    }
}

How can I get similar effect, so object can be delivered to concrete method instead of the general one?

------------------------Serveral Parameters Example--------------

class Parent {}

class Child1 extends Parent {}

class Child2 extends Parent {}

class Main {
    static void method(Parent obj1, Parent obj2) {}

    static void method(Child1 obj1, Child1 obj2) {}

    static void method(Child1 obj1, Child2 obj2) {}

    public static void main(String[] arg) {
        Parent obj1 = new Child1();
        Parent obj2 = new Child2();
        method(obj1, obj1); //call method(Child1 obj1, Child1 obj2)
        method(obj1, obj2); //call method(Child1 obj1, Child2 obj2)
    }
}
1
  • 1
    @ernest_k visitor design pattern is a good way for this example, but if a method has several parameters which inherits Parent, it seems not work. Commented Dec 20, 2018 at 10:55

3 Answers 3

1

What you are asking about it method overloading. Method overloading is resolved at compile time, and therefore uses the compile-time type of the relevant variables to determine which method to execute.

Therefore method(obj1) and method(obj2) will always call static void method(Parent obj), since the compile time type of obj1 and obj2 is Parent.

Sign up to request clarification or add additional context in comments.

Comments

0

Background: I come up with nearly the same problem when writing a compiler project.

Short Answer: If you stick to making the code extensible and easy to write as well (just as code samples in the question), presumably, you have to add reflections to it (though it may not be friendly to static analyzers).

Example:

import java.lang.reflect.*;
import java.util.*;

class Value {}

class IntValue extends Value {
    private int value;
    public int value() {
        return value;
    }
    public IntValue(int value) {
        this.value = value;
    }
    public String toString() {
        return String.valueOf(value);
    }
}

class StringValue extends Value {
    private String value;
    public String value() {
        return value;
    }
    public StringValue(String value) {
        this.value = value;
    }
    public String toString() {
        return value;
    }
}

class Operator {
    public Value apply(Value x, Value y) throws ArithmeticException {
        try {
            var method = this.getClass().getDeclaredMethod("apply", x.getClass(), y.getClass());
            return (Value) method.invoke(this, x, y);
        } catch (InvocationTargetException exception) {
            throw (ArithmeticException) exception.getCause();
        } catch (Exception ignore) {
            return null;
        }
    }

    private IntValue apply(IntValue x, IntValue y) {
        return new IntValue(x.value() / y.value());
    }

    private StringValue apply(StringValue x, StringValue y) {
        return new StringValue(x.value() + y.value());
    }
}

public class Main {
    public static void main(String[] args) {
        var op = new Operator();

        System.out.println(op.apply(new IntValue(6), new IntValue(2)));
        System.out.println(op.apply(new StringValue("a_str"), new StringValue("b_str")));

        try {
            System.out.println(op.apply(new IntValue(6), new IntValue(0)));
        } catch (ArithmeticException exception) {
            exception.printStackTrace();
        }
    }
}

Let me know if you have better solutions.

Comments

0

I found solution like this:

class Parent {}

class Child1 extends Parent {}

class Child2 extends Parent {}

public class Main {
    static void method(Parent obj) {
        System.out.println("Parent");
        if(obj instanceof Child1)
        {
            method((Child1) obj);
            return;
        } else if(obj instanceof Child2)
        {
            method((Child2) obj);
            return;
        }
    }
    static void method(Child1 obj) {
        System.out.println("Child1");
    }
    static void method(Child2 obj) {
        System.out.println("Child2");
    }
    public static void main(String[] arg) {
        Parent obj1 = new Child1();
        Parent obj2 = new Child2();
        method(obj1); //call method(Child1 obj)
    }
}

For this code the output is :

Parent
Child1

So it means that when we put the object of type Child1 then method for Parent will be invoked and then it checks inside this method if object is type of Child1, if yes then invoke method for Child1.

Until the object passed as argument to this method is type of Parent there is no way to invoke Child1 or Child2

1 Comment

but if Parent has lots of child classes, these if-else1 clauses will be ugly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.