如何从不可知函数调用多态函数?

时间:2012-06-19 21:06:02

标签: java oop

我有一个方法foo

void foo (String x) { ... }
void foo (Integer x) { ... }

我希望从一个不关心参数的方法中调用它:

void bar (Iterable i) {
  ...
  for (Object x : i) foo(x); // this is the only time i is used
  ...
}

上面的代码抱怨我没有定义foo(Object),当我添加

void foo (Object x) { throw new Exception; }

然后bar(Iterable<String>)调用而不是foo(String)并抛出异常。

如何避免对bar(Iterable<String>)bar(Iterable<Integer>)两个文本相同的定义?

我以为我能够摆脱像

这样的东西
<T> void bar (Iterable<T> i) {
  ...
  for (T x : i) foo(x); // this is the only time i is used
  ...
}

然后我收到cannot find foo(T)错误。

3 个答案:

答案 0 :(得分:2)

您面临的问题是重载方法在编译时受到约束。在您的示例中,编译器尝试确定要调用的foo()方法中的哪一个。但是,示例中最强的静态类型x是Object,并且没有方法foo(Object),因此编译器说它无法调用适当的方法。

如果添加foo(Object)方法,无论x的实际运行时类型是什么,您都将始终调用foo(Object)方法。

此问题扩展到使用泛型。由于T可以是任何类型,因此您必须具有通用方法foo(T),否则您的代码将无法编译。但是,如果添加该方法,则无法在不同的参数类型之间识别这些方法,因为只会调用foo(T)

解决这个问题的唯一方法是逐个案例检查,并像其他答案一样进行投射。除非参数类型是您定义的类,否则它们都可以实现公共接口。然后你可以做类似的事情:

interface ArgumentType {
   void callback(FooClass c);
}

class YourClassA implements ArgumentType {
    void callback( FooClass c ) {
         c.foo( this );
    }
}
对于FooClass的每个实现类,

foo()仍然必须有ArgumentType方法,但这样您就可以按类型不可知进行选择。

答案 1 :(得分:1)

以这种方式思考:如果foox,应该调用哪个版本的Object

这就是JVM面临的问题。

如果你想要一个真正的多态方法,那么你需要明确地写一个。然后,这样的方法可以通过内省检查Object以查看它的实际类类型是什么,并在此之后调用适当的方法。

,您可以仔细查看foo的内容。是否只调用Object定义的方法?如果是这样,只需创建一个执行必需品的void foo(Object x)方法。

答案 2 :(得分:1)

问题是你试图找到foo(Object x)而String和Integer都是对象,并不是所有的对象都是String或Integer,而java也不会缩小到正确的类。

我或许会建议创建一个方法:

void foo(Object o){
     if ( o instanceof String){
         String s = (String) o;
         //Deal with s
     } else if ( o instanceof Integer){
         Integer i = (Integer) o;
         //Deal with i
     }
}

另外,如果你正在使用泛型,你不应该在bar中传递原始迭代器