2

我对 Java 比较陌生,希望对以下查询有任何帮助。我已经定义了两个类——为了简单起见,我们称它们AB. Class A有一个名为 的方法methodA,并且Class B有一个名为 的方法methodB。这两个类的对象包含在一个ArrayList被调用的container. 我需要做的是循环ArrayList并根据对象的类型调用不同的方法。

这是我目前的代码:

for (Object item : container) {
    if (item instanceof A) {
        item.methodA()
    } else if (item instanceof B) {
        item.methodB() 
    }
}

我的 IDE (NetBeans) 不会编译上面的代码,因为itemtypeObject没有methodAor methodB。有没有其他方法可以编写循环来完成我需要它做的事情?谢谢。

4

4 回答 4

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(); 
}

访问者模式是此类代码的另一种常见解决方案,当您想要在一组固定的类中支持一堆不同的常见操作而不不断修改这些类时,它很有用。

于 2013-06-30T18:52:12.897 回答
2

您正在处理变体问题,Java(以及几乎任何其他广泛使用的语言)对此没有很好的答案。Scala 通过案例类解决了这个问题,而像 ML 这样的更多学术语言可以轻松处理它。

以上所有答案都建议使用 if-ladders 和 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();
        }
    } );
}
于 2013-06-30T20:56:13.087 回答
0

只需在调用方法之前将类型转换为 A 或 B。在调用方法之前将项目转换为 A 或 B

for (Object item : container) {
    if (item instanceof A) {
       ((A) item).methodA();;
    } else if (item instanceof B) {
       ((B) item).methodB();
    }
}
于 2013-06-30T18:52:52.623 回答
0

以这种方式尝试

       if (item instanceof A) {
            ((A) item).methodA();
        } else if (item instanceof B) {
            ((B) item).methodB();
        }
于 2013-06-30T18:59:17.293 回答