Java 如何从不可知函数调用多态函数?
我有一个方法Java 如何从不可知函数调用多态函数?,java,oop,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 E
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)
调用它而不是foo(String)
并抛出异常
如何避免对bar(Iterable)
和bar(Iterable)
有两个文本上相同的定义
我以为我能逃脱这样的惩罚
<T> void bar (Iterable<T> i) {
...
for (T x : i) foo(x); // this is the only time i is used
...
}
空栏(i表i){
...
for(tx:i)foo(x);//这是唯一一次使用我
...
}
但是我得到了
找不到foo(T)
错误。这样想:如果x
是对象,应该调用foo
的哪个版本
这就是JVM面临的问题
如果您想要一个真正的多态方法,那么您需要显式地编写一个。这样的方法可以通过内省检查对象
,查看它的实际类类型,然后调用适当的方法
或者,您可以仔细看看foo
的功能。它是否仅调用由对象定义的方法?如果是这样,只需创建一个执行必要操作的void foo(Object x)
方法。您面临的问题是重载方法在编译时绑定。在您的示例中,编译器试图找出要调用的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
对于ArgumentType
的每个实现类仍然必须有一个foo()
方法,但是这样你就可以通过类型不可知来进行选择。问题是你试图找到foo(对象x)
,而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中传递原始迭代器可能的重复项。您能解释一下“最强的静态类型”是什么意思吗?谢谢我所说的“最强静态类型”是指编译器可以为变量x推断出的最具体的类型。例如,原则上,如果您有以下代码:对象x;x=新整数();foo(x);智能编译器可以确定调用站点上的x的类型是整数,并可以调用适当的方法。在您的示例中,这是不可能的,因为代码中没有任何提示类型的内容。因此,编译器知道的“最强”类型是对象。