一种查找Java对象初始化而不是声明类型的方法?

use*_*831 2 java visitor-pattern

我不知道我在这里是否遗漏了什么,但我无法将对象转换为其实际的初始化类型.基本上,如果我用"SuperClass sc = new SubClass()"创建一个对象,那么我在sc上调用一个方法,我希望该方法能够调用方法(Subclass)而不是方法(Superclass).示例如下:

public class Example
{
    public static void act(SuperClass a) {
        System.out.println("SuperClass");
    }

    public static void act(SubClass a) {
        System.out.println("SubClass");
    }

    public static void main(String[] args) {
        SuperClass sc = new SubClass();

        // want to find a way to call act(SubClass) instead of act(SuperClass)
        act(sc);
   }
}

class SuperClass {}
class SubClass extends SuperClass {}
Run Code Online (Sandbox Code Playgroud)

我现在正在使用访问者模式,但我想知道是否有其他方法可以通过Java Reflection API进行此操作?

非常感谢提前!

==编辑==

我知道通常使用OO最好将功能强加回超类/子类本身,但对于我的特定用例,我有一堆子类是不可变的模型类,应该传递给不同类型的执行引擎(想想不同的"示例"类).子类/模型类应该只保存不可变信息,而实际的实际功能在于执行引擎(Example类).这就是为什么我想知道访客模式的替代方案.有没有人有办法在Java中恢复实际的"初始化"信息?如果是这样,非常感谢你.

而且由于问题的本质,我不能使用直接投射......想象一下,如果我有一个SuperClass的arraylist,其中每个元素可能是SubClass1,SubClass2,SubClass3,都是从SuperClass扩展的.

现在,当你从Arraylist中取出东西时,你得到一个SuperClass对象,即使它们可能真的是SubClass1,SubClass2,SubClass3等.

接下来,我想调用act(SubClass1),并能够在当前类型上调用正确的act()方法.所以我想最终调用act(SubClass1),act(SubClass2),act(SubClass3),而不是act(SuperClass).

==再次编辑==

我通过Java Reflection API想出了一种方法,通过使用Class.forName(classname)查找SubClass的实际底层类型,然后使用正确的方法签名动态调用该方法.对于那些对此问题感兴趣的人,我已经在本页的某个地方以答案的形式写了这篇文章.请注意,这不是一种非常有效的方式来完成我在这里尝试做的事情,如果你遇到我的情况,你最好使用访问者模式或if-else语句.


所以Nicola Musatti给出的答案最接近于回答我的问题,尽管正如他已经指出的那样,随着SubClasses数量的增长,if-else语句列表变得非常长.我将选择他的答案作为接受答案,因为我在我的问题中没有明确说明我希望避免if-else检查.

无论如何,所以我今天使用Java Reflection API玩了一下并想出了这个:

SuperClass sc = new SubClass();

// Get the actual class of sc. actualClass now is SubClass.
Class actualClass = Class.forName(sc.getClass().getCanonicalName());

// Basically invoking act(SubClass sc) instead of act(SuperClass sc)
Class parameters[] = {actualClass};
Method method = Example.class.getMethod("act", parameters);
Object arguments[] = {sc};
method.invoke(null, arguments);
Run Code Online (Sandbox Code Playgroud)

这肯定不是一种很好的方法,尤其是因为Java Reflection API带来的性能损失.这可能比访问者模式或if-else检查更好,如果你有一百万个子类,因为它可能需要管理的代码较少,但是我现在仍然坚持使用访问者模式,因为我没有一百万个子类来管理.

无论如何,只是想我会在这里发布,以表明它可以完成,只为那些好奇的人.

Paw*_*rok 6

你不应该定义act()SuperClassSubClass?这样,无论对象的引用类型如何,都将调用正确的方法.

编辑:如果我没记错的话,访问者模式定义了类似于accept()要访问的元素的方法,允许访问者以多态方式访问它在被访问元素中感兴趣的内容.