如何在Java中给定特定参数类的情况下调用不同的方法

时间:2018-12-20 09:59:40

标签: java inheritance polymorphism

假设我们有以下代码:

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)
    }
}

如何获得类似的效果,因此可以将对象传递给具体方法而不是一般方法?

------------------------服务器参数示例--------------

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)
    }
}

3 个答案:

答案 0 :(得分:1)

您在问什么方法重载。方法重载是在编译时解决的,因此使用相关变量的编译时类型来确定要执行的方法。

因此,method(obj1method(obj2)将始终调用static void method(Parent obj),因为obj1obj2的编译时间类型为Parent。 / p>

答案 1 :(得分:0)

我找到了这样的解决方案:

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)
    }
}

对于此代码,输出为:

Parent
Child1

因此,这意味着当我们放置类型为Child1的对象时,将调用Parent方法,然后在此方法中检查对象是否为Child1类型,如果是,则为Child1调用方法。

除非作为参数传递给此方法的对象是Parent类型,否则无法调用Child1或Child2

答案 2 :(得分:0)

背景:编写编译器项目时,我遇到几乎相同的问题。

简短答案:如果您坚持使代码可扩展,并且易于编写(就像问题中的代码示例一样),那么大概必须添加反射(尽管它可能对静态分析仪不友好)。

示例:

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();
        }
    }
}

如果您有更好的解决方案,请告诉我。