如何在多态函数中传递父类实例来代替子类实例?

时间:2014-06-24 21:29:24

标签: java generics

我有两个班级Event1Event2。在运行时,我想使用java反射创建Event1Event2的实例,并将其作为参数传递给另一个函数。该函数是一个多态函数,它根据输入参数类型调用相应的函数。

由于我不知道我可能需要在运行时创建什么类型的子事件实例,因此我将来自'事件'类并创建父类实例。我的问题是,我可以通过'事件' class作为参数,将在运行时解析为多态函数的子类之一。

这是我的代码。

public void myFunc(){

    String qualifiedName = new String("events.Event1"); // Event1 info is actually obtained at runtime. 

    Class cls = Class.forName(qualifiedName);
    Event baseEvent = (Event) cls.getDeclaredConstructor().newInstance(); 
    // I want to create an instance like, Event ev1 = new Event1(); and pass it as a parameter.

    observer.update(baseEvent);  // I get compile time error because no update method takes `Event` class instance as parameter.
}

包含多态函数的Observer类。

public void update(Event1);
public void update(Event2);

Java泛型可以帮助吗?感谢。

3 个答案:

答案 0 :(得分:3)

试试这个:

    Method method = observer.getClass().getDeclaredMethod("update", baseEvent.getClass());
    method.invoke(observer, baseEvent);

答案 1 :(得分:0)

首先是一些术语:如果你在同一个类/接口中有一个同名但方法不同的方法,就像这样:

public void update(Event1 e);
public void update(Event2 e);

它被称为重载,而不是多态。 (很高兴知道你是否想在这个主题上搜索一些东西)。

第二,回答你的问题:没有.Java多态性对此意味着什么。如果你这样调用以前的更新方法:

Event e = //get Event from anywhere
update(e);

编译器将无法决定要调用的update()的重载版本,因为Java多态不会对重载方法起作用。

您可以尝试将其投射以查看它实际上是什么类型:

try {
    update((Event1) e);
} catch(ClassCastException ex) {
    //do nothing
}
try {
    update((Event2) e);
} catch(ClassCastException ex) {
    //do nothing
}

如果e实际上是Event1Event2,则会调用正确的方法。但是这需要在编译时知道Event的所有子类(除非你想弄脏并使用反射)。

答案 2 :(得分:0)

顺便说一句..我更喜欢这种方法(避免反思):

Map<Class<? extends Event>,Runnable> actionMapper= new HashMap<Class<? extends Event>, Runnable>();
    actionMapper.put(Event1.class, new Runnable() {

        @Override
        public void run() {
            System.out.println("Execution for event 1");
        }
    });

    actionMapper.put(Event2.class, new Runnable() {

        @Override
        public void run() {
            System.out.println("Execution for event 2");
        }
    });


    Event event= new Event1();
    Runnable action = actionMapper.get(event.getClass());
    action.run();