我对Java相对较新,并希望对以下调查有任何帮助。我已经定义了两个类 - 为简单起见,我们称之为A
和B
。 Class A
有一个名为methodA
的方法,Class B
有一个名为methodB
的方法。这两个类的对象包含在名为ArrayList
的{{1}}中。我需要做的是遍历container
并根据对象的类型调用不同的方法。
这是我目前的代码:
ArrayList
我的IDE(NetBeans)不会编译上述代码,因为类型为for (Object item : container) {
if (item instanceof A) {
item.methodA()
} else if (item instanceof B) {
item.methodB()
}
}
的{{1}}没有item
或Object
。有没有其他方法来编写循环来完成我需要它做的事情?感谢。
答案 0 :(得分:5)
您需要添加演员表。仅仅因为你检查过该项是A(或B)的实例,就不允许你在项目上调用A方法。
if (item instanceof A) {
((A) item).methodA();
} else if (item instanceof B) {
((B) item).methodB();
}
但是,一般情况下,您可能需要考虑重构代码以避免此模式。例如,您可以创建A和B实现的基类的公共接口:
public interface MyInterface {
void doSomething();
}
class A : MyInterface {
...
public void doSomething() { this.methodA(); }
}
class B : MyInterface {
...
public void doSomething() { this.methodB(); }
}
然后你可以这样做:
List<MyInterface> list = // a list of A's and B's
for (MyInterface item : list) {
// use polymorphism to invoke the appropriate method
item.doSomething();
}
visitor pattern是此类代码的另一种常见解决方案,当您希望在固定的一组类中支持大量不同的常见操作而不必不断修改这些类时,此代码非常有用。
答案 1 :(得分:2)
您正在处理 variants 问题,Java(以及几乎所有其他广泛使用的语言)都没有很好的答案。 Scala通过案例类解决了这个问题,而像ML这样的学术语言可以轻松处理它。
所有上述答案都建议使用if-ladder和cast,这是Java中最简洁的解决方案,但它基本上放弃了完整的编译时安全性。如果您不喜欢演员表,可以使用访客模式来解决问题。它就像你能得到的那样冗长,但它完全是类型安全的。
interface ABVariantVisitor {
void visit( A a );
void visit( B b );
}
interface ABVariant {
void accept( ABVariantVisitor v );
}
class A implements ABVariant {
// ...
void accept( ABVariantVisitor v ) {
v.visit( this );
}
// ...
}
class B implements ABVariant {
// ...
void accept( ABVariantVisitor v ) {
v.visit( this );
}
// ...
}
List< ABVariant > container;
// ...
for ( ABVariant item : container ) {
item.accept( new ABVariantVisitor() {
@Override void visit( A a ) {
a.methodA();
}
@Override void visit( B b ) {
b.methodB();
}
} );
}
答案 2 :(得分:0)
在调用方法之前,只需对A或B进行类型转换。在调用方法之前将项目转换为A或B
for (Object item : container) {
if (item instanceof A) {
((A) item).methodA();;
} else if (item instanceof B) {
((B) item).methodB();
}
}
答案 3 :(得分:0)
尝试这种方式
if (item instanceof A) {
((A) item).methodA();
} else if (item instanceof B) {
((B) item).methodB();
}