我不知道我是否遗漏了什么,但我在将对象转换为其实际的初始化类型时遇到了问题。基本上,如果我用“SuperClass sc = new SubClass()”创建一个对象,然后我在 sc 上调用一个方法,我希望该方法能够调用方法(子类)而不是方法(父类(super class))。示例如下:
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 {}
我现在正在使用访问者模式,但我想知道是否有其他方法可以做到这一点,也许是通过 Java 反射 API?
提前致谢!
== 编辑 ==
我知道一般来说,对于 OO 来说,最好将功能粘回到父类(super class)/子类本身,但对于我的特定用例,我有一堆子类是不可变的模型类,应该传递给不同类型的执行引擎(想想不同的“示例”类)。子类/模型类应该只包含不可变信息,仅此而已,实际的真正功能在于执行引擎(示例类)。这就是为什么我想知道访问者模式的替代方案。有没有人有办法恢复 Java 中实际的“初始化”信息?如果是这样,非常感谢。
而且由于问题的性质,我不能使用直接转换... 想象一下,如果我有一个 SuperClass 的数组列表,其中每个元素可能是 SubClass1、SubClass2、SubClass3,它们都是从 SuperClass 扩展而来的。
现在,当您从 Arraylist 中提取内容时,您会得到一个 SuperClass 对象,即使它们实际上可能是 SubClass1、SubClass2、SubClass3 等。
接下来,我想调用 act(SubClass1),并能够对当前类型调用正确的 act() 方法。所以我想结束调用 act(SubClass1)、act(SubClass2)、act(SubClass3),而不是 act(SuperClass)。
== 再次编辑==
我想出了一种通过 Java 反射 API 实现此目的的方法,方法是使用 Class.forName(classname) 查找子类的实际基础类型,然后使用正确的方法签名动态调用该方法。对于对此问题感兴趣的人,我已将其以答案形式写在本页下方的某个位置。请注意,这不是完成我在这里尝试做的事情的非常有效的方法,如果您遇到我的情况,您最好使用访问者模式或 if-else 语句。
所以 Nicola Musatti 给出的答案最接近于回答我的问题,尽管正如他也指出的那样,随着子类数量的增加,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);
这肯定不是做事的好方法,特别是因为 Java 反射 API 强加的性能损失。这可能比访问者模式或 if-else 检查你是否有一百万个子类要好,因为它可能需要更少的代码来管理,但是我现在会坚持使用访问者模式,因为我没有一百万个子类要管理.
无论如何,只是想我会在这里发布这个来证明它是可以做到的,只是为了那些好奇的人。
最佳答案
你不应该在 SuperClass
和 SubClass
中定义 act()
吗?这样,无论对象引用的类型如何,都会调用正确的方法。
编辑:如果我没记错的话,访问者模式在要访问的元素上定义了类似 accept()
的方法,它允许访问者以多态方式访问所访问元素中它感兴趣的任何内容。
关于java - 一种查找 Java 对象初始化为什么而不是声明类型的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6899326/