Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从不可知函数调用多态函数?_Java_Oop - Fatal编程技术网

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的类型是整数,并可以调用适当的方法。在您的示例中,这是不可能的,因为代码中没有任何提示类型的内容。因此,编译器知道的“最强”类型是对象。