我有一组具有共同超类的POJO。它们存储在超类类型的二维数组中。现在,我想从数组中获取一个对象并使用子类的方法。这意味着我必须将它们转换为子类。有没有办法在不使用 instanceof 的情况下执行此操作?
更新:作为具体示例:http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/请参阅:“点击敌人时添加新动作(攻击)”
答案 0 :(得分:6)
是的 - 您可以通过反转流来完成它:当基类的实例是特定类型时,代替您的代码执行操作,将操作项传递给对象,并让对象决定是否执行它或不。这是Visitor Pattern背后的基本技巧。
interface DoSomething {
void act();
}
abstract class AbstractBaseClass {
abstract void performAction(DoSomething ds);
}
class FirstSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
ds.act();
}
}
class SecondSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
// Do nothing
}
}
AbstractBaseClass array[] = new AbstractBaseClass[] {
new FirstSubclass()
, new FirstSubclass()
, new SecondSubclass()
, new FirstSubclass()
, new SecondSubclass()
};
for (AbstractBaseClass b : array) {
b.performAction(new DoSomething() {
public void act() {
System.out.println("Hello, I'm here!");
}
});
}
答案 1 :(得分:4)
如果您知道他们属于子类类型,那么只需直接投射它们而不进行instanceof
检查。
但是将它们放在一个超类型数组中是告诉编译器丢弃它们实际上属于子类类型的信息。您的超类应该公开那些方法(可能是抽象的),或者您的数组应该是子类类型(因此您不会告诉编译器忘记对象的实际类型),或者您必须将其吸收并进行演员表演(可能使用instanceof
测试)。
唯一另一个值得注意的选择是您可以尝试访问者模式,该模式将操作传递给对象并让对象决定如何处理它。这允许您覆盖要忽略的类或根据其运行时类型执行操作。
答案 2 :(得分:2)
您可以尝试使用访问者设计模式。 http://en.wikipedia.org/wiki/Visitor_pattern
你必须问自己,为什么你需要知道他们的类型,也许这可以用超类中的抽象方法来代替,每个人都可以根据所需的结果来实现。
abstract class A{
abstract void visit();
}
class B extends A{
void visit() { print("B"); }
}
class C extends A {
void visit() { print("C"); }
}
答案 3 :(得分:1)
我会避免在第一时间施放它们。
真的想想你要做什么,以及他们是否应该在同一个系列中。
如果你有类似的东西
for(MyObj o : array) {
if(o instanceof A) {
((A)o).doA();
}
if(o instanceof B) {
((B)o).doB();
}
}
考虑这个
abstract class MyObj {
abstract void doIt();
}
class A {
void doIt() { doA(); }
}
class B {
void doIt() { doB(); }
}
答案 4 :(得分:0)
将方法暴露在超类中,然后使用覆盖。在基类中提供一个空实现,以便子类可以在需要时忽略该操作。