我有一个类层次结构,看起来有点像这样:
class Parent { }
class Child1 extends Parent {}
class Child2 extends Parent {}
class Child3 extends Parent {}
在另一个课程中,我的方法看起来像这样:
void doSomething(Parent p) { //default }
void doSomething(Child1 c) { //implementation for Child 1 }
void doSomething(Child2 c) { //implementation for Child 2 }
目前,当我有这样的事情时
Parent p = new Child2();
doSomething(p);
第一种方法是调用doSomething(Parent)
而不是doSomething(Child2)
假设我有一个静态类型为Parent且动态类型为ChildN的项目列表。如何在不进行强制转换的情况下调用动态类型,如何确保方法。仅适用于Child3(没有特定的doSomething方法)我想调用默认实现。
答案 0 :(得分:3)
您正在寻找的是“多调度或”动态调度“ - 并且在Java中不存在。
在Java中,编译器决定在重载的情况下选择哪种方法。 (当你有三个具有相同名称但参数类型不同的方法时会发生这种情况)。这发生在编译时,如果你的“运行时”父对象碰巧是Child1对象;没关系。因为编译器修复要调用的方法 - 如上所述:java不支持动态调度。
从这个意义上讲,正确的Java解决方案是在您的Parent类中放置一个方法“doSomething()”;并让每个孩子覆盖该方法到特定事物。
如果“doSomething()”并不真正“适合”这个类;你可以看一下visitor pattern。另一个选择是使用instanceof ...但是你应该使用多态来“隐藏”相应的if / else链...,如:
interface DoIt { void doSomething() }
class ParentDoIt implements DoIt ...
same for Childs
class DoItFactory {
DoIt getDoIt(Parent p) {
if (p instanceof Child1) return new Child1DoIt(p)
...
答案 1 :(得分:2)
解决方案可能是doSomething方法使用参数中的逻辑:
class Parent {
public void neededMethod() {//default}
}
class Child1 {
public void neededMethod() {//implementation for Child 1}
}
然后在你的代码中:
void doSomething(Parent p) {
//more code
p.neededMethod();
// code
}
如果此解决方案不适合您,因为您需要某种调度程序,那么您必须使用instanceof
然后调用正确的方法:
void doSomething (Parent p) {
if (p instanceof Child1) doSomethingWithChild1(p);
else if (p instanceof Child2) doSomethingWithChild2(p);
...
else defaultSomething(p);
}
答案 2 :(得分:0)
我会这样做。
interface SomeAction { void doSomething(); }
class Parent implements SomeAction { //override doSomething here }
class Child1 extends Parent {//override doSomething here }
class Child2 extends Parent {//override doSomething here }
class Child3 extends Parent { // no need to override here}
现在
在另一个课程中,我的方法看起来像这样
void doSomething(SomeAction p) { //default }
Parent p = new Child2();
doSomething(p);
p.doSomething(); // would call Child 2