我有一些具有相同界面类型的不同对象的arraylist,例如:
Interface interface {}
class A implements interface {}
class B implements interface {}
我还有一个重载方法,它实现了接口的所有继承对象:
public void doSomething(A obj) {}
public void doSomething(B obj) {}
编译器还强制我用接口编写重载方法:
public void doSomething(interface obj) {}
然后我浏览列表的值并调用方法:
for (interface obj: myList) {
doSomething(obj);
}
现在因为obj的类型是'interface',所以在obj实际上是B类的情况下调用doSomething(接口obj)而不是doSomething(B obj)。
我可以让java做其他的,所以当obj是A类时调用doSomething(A obj),当obj是B类时调用doSomething(B obj)吗?
答案 0 :(得分:3)
Java使用早期绑定,这意味着obj的类型是在编译期间定义的,而不是在运行时定义的。由于您的代码表明obj是接口类型,因此编译器将始终调用将接口作为参数的方法。
你有两种选择让它调用正确的方法:
(非常难看)在调用对象时使用instanceof和cast检查obj类型。
for (interface obj: myList) {
if(obj instanceof A)
doSomething((A) obj);
else if(obj instanceof B)
doSomething((B) obj);
else
doSomething(obj); // Calls the method receiving Interface
}
在界面中实现访问者方法,因此A和B都会在访问时调用方法doSomething(this)。
interface Interface {
void visit(OtherClass methodHolder);
}
class A implements Interface {
public void visit(OtherClass methodHolder) {
methodHolder.doSomething(this);
}
}
class B implements Interface {
public void visit(OtherClass methodHolder) {
methodHolder.doSomething(this);
}
}
答案 1 :(得分:2)
有一个技巧。免责声明:这很难看。
如果使用doSomething方法的类被称为类Performer,如:
class Performer {
void doSomething(A x);
void doSomething(B x);
void doSomething(Inf x);
}
您可以添加到您的界面Ifc:
interface Ifc {
void acceptPerformer(Performer p);
}
在A和B类中都实现如下:
void acceptPerformer(Performer p) {
p.doSomething(this);
}
并实现这样的doSomething(Ifc x)方法:
void doSomething(Ifc x) {
x.acceptPerformer(this);
}
这听起来很奇怪,但确实有效。当调用接受接口的doSomething方法时,它将调用具体类上的acceptPerformer。当该类重新调用doSomething时,它将知道它是哪种类型,并将调用正确的doSomething!
答案 2 :(得分:0)
这里的多态方法是在doSomthing()
中定义interface
并在A
和B
中实现它,然后在循环中调用它。根据具体对象,将运行不同的代码。
答案 3 :(得分:0)
是方法
public void doSomething(interface obj)
定义为界面的一部分?如果编译器强迫你编写方法,这是唯一有意义的事情。
这就引出了为什么要尝试更改实现中接口的方法签名的问题。该接口旨在成为对象外观的契约。
答案 4 :(得分:-1)
您可以使用Java instanceof
运算符来检查哪个类实现了您的接口:
if(obj instanceof A) {
// do something
} else {
// do something else
}
但更好的方法是让一个方法只接受你所创建的接口实例的任何对象,如Atmocreations所述。