假设我有一个带有一个参数的方法,根据参数的类型,该方法应该做不同的事情。
让我们调用方法doMethod()
:
private int doMethod(Class1 x) {
// do something with x
}
private int doMethod(Class2 x) {
// do someting else with x
}
...
我有几个这样的方法。现在我的问题来了: 我有一个不同的方法,它接受一个参数,该参数是上面所有其他类的父类(super class)(但实际上它总是它的子类之一):
private void otherMethod(SuperClass obj) {
// I do something clever with obj,
// which is the super class of Class1, Class2, .. Classn
// however this method is always called with either Class1, Class2, etc.
// never with an instance of SuperClass itself.
// finally I want to execute doMethod() on obj:
int result = doMethod(obj);
// fails because doMethod(SuperClass) does not exist
}
所以最后我创建了一个 doMethod(Superclass obj)
,用 instanceof
检查 obj 然后调用 doMethod()
Actor 。
一定有更好的方法来做到这一点,不是吗?我只是暂时想不起来,所以也许有人可以帮助我:)
非常感谢!
最佳答案
几种可能性:
子类 + 访问者模式
如果不是最终的,您可以为每个子类创建一个子类。您可以让他们提供一个 visit()
方法并使用 Visitor 模式实现您的附加操作 doMethod()
。这将开启以后添加不同操作的可能性。 Visitor 模式,如果做得好,应该不会忘记将操作添加到新的子类(因为它不会编译)。这可能是好事,也可能不是好事,具体取决于您的需要。
子子类是我不喜欢的关于此解决方案的部分。这里有爆炸类层次结构和复杂性的危险:如果可能的话,我会让你添加的额外子类成为最终类。如果您正在扩展的任何类在将来成为最终类(向后兼容性中断,但并非不可能),您也会遇到麻烦。
此处示例:http://www.javacodegeeks.com/2013/08/visitor-design-pattern-in-java-example-tutorial.html (在此示例中,开发人员可以访问基类并在其中添加 visit()
方法,而您必须将其添加到由额外子类实现的通用接口(interface)中)。
聚合+访客模式
上述的一个变体是创建一个平行的类层次结构,其中您自己的类包含(而不是子类)来自其他层次结构的类的实例。您将 visit()
添加到您自己的类层次结构(以及您想要的任何其他方法),并且还提供了一种访问底层类型的方法。你应该能够用泛型很好地包装它。
同样,这里可能存在很多复杂性。
“处理程序” map
您可以在以实例类型为键的映射中查找作为接口(interface)实现的操作。
// Java-y pseudo-code...
Map<Class<? extends SuperClass>,Function<V,R>> doMethods = new HashMap<>();
doMethods.add(FooClass.class, FooDoMethod.INSTANCE);
doMethods.add(BarClass.class, BarDoMethod.INSTANCE);
...
public R doMethod(V it) {
Class<? extends V> cls = it.getClass();
Function<? extends V,R> fn = doMethods.get(cls);
if(fn==null)
throw new UnsupportedOperationException(
"Can't doMethod() on a "+cls.getName());
return fn.apply(it);
}
这里的 INSTANCE
单例对象将实现类似于 Java 1.8 中新的 Function
接口(interface)(或 1.8 之前的 Comparable)的东西 - 即是具有单一方法的接口(interface)的实现实现操作。然后,您可以通过向映射添加更多条目来扩展支持该操作的类型。您将需要为每个支持的类型添加一个显式条目(即使是中间基类,如果它们实际上可以有实例 - 类似于 JComponent 和 JButton,在 Swing 中(两者都可以存在一个真实的实例)。当然,你可以,为多种类型添加相同的实现,如果它们以相同的方式实现的话。
然后您可以在其他一些类中隐藏对映射处理程序(和映射本身)的调度。
(附言,抱歉,手头没有 javac,否则我会正确地尝试这些。)
关于Java方法重载和调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19909213/