简体   繁体   English

避免实例

[英]avoiding instanceof

I have a set of POJOs with a common superclass. 我有一组具有共同超类的POJO。 Those are stored in a two-dimensional array of type superclass . 它们存储在类型超类的二维数组中。 Now, I want to obtain an object from the array and use methods of the subclass . 现在,我想从数组中获取一个对象并使用子类的方法。 This means I have to cast them to the subclass . 这意味着我必须将它们转换为子类 Is there a way to do this without using instanceof ? 有没有办法在不使用instanceof的情况下执行此操作?

Update: As a concrete example: http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/ See: "Add new actions (attack) when an enemy is clicked" 更新:作为一个具体的例子: http//obviam.net/index.php/the-mvc-pattern-tutorial-building-games/请参阅: “点击敌人时添加新动作(攻击)”

Yes - you can do it by inverting the flow: instead of your code doing something when the instance of the base class is of a specific type, pass an action item to the object, and let the object decide whether to perform it or not. 是的 - 您可以通过反转流来完成:当基类的实例是特定类型时,代替您的代码执行操作,将操作项传递给对象,并让对象决定是否执行它。 This is the basic trick behind the 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!");
        }
    });
}

If you know they're of the subclass type, then just cast them directly without an instanceof check. 如果您知道它们属于子类类型,那么只需直接转换它们而不进行instanceof检查。

But putting them in a superclass-typed array is telling the compiler to discard the information that they're actually of the subclass type. 但是将它们放在一个超类型数组中告诉编译器丢弃它们实际上属于子类类型的信息。 Either your superclass should expose those methods (perhaps as abstract), or your array should be of the subclass type (so you're not telling the compiler to forget the actual type of the objects), or you'll have to suck it up and do the cast (possibly with the instanceof test). 您的超类应该公开那些方法(可能是抽象的),或者您的数组应该是子类类型(因此您不会告诉编译器忘记对象的实际类型),或者您必须将其吸收并执行转换(可能使用instanceof测试)。

The only other notable alternative is that you might experiment with the visitor pattern, which passes an action to the object and lets the object decide what to do with it. 唯一另一个值得注意的替代方案是您可以尝试访问者模式,该模式将操作传递给对象并让对象决定如何处理它。 That lets you override classes to ignore or perform the actions based on their runtime type. 这允许您覆盖要忽略的类或根据其运行时类型执行操作。

You can try to use the Visitor design pattern. 您可以尝试使用访问者设计模式。 http://en.wikipedia.org/wiki/Visitor_pattern http://en.wikipedia.org/wiki/Visitor_pattern

You have to ask yourself, why do you need to know their type, maybe this can be replaced with the use of an abstract method in the super class, that every one of them can implement according the desired result. 你必须问自己,为什么你需要知道它们的类型,也许这可以用超类中的抽象方法替换,每个人都可以根据所需的结果实现。

abstract class A{
    abstract void visit();
}

class B extends A{
    void visit() { print("B"); }
}

class C extends A {
    void visit() { print("C"); }
}

I would avoid casting them in the first place. 我会避免在第一时间施放它们。

Really think about what you're trying to do, and if they should be in the same collection like that. 真的想想你要做什么,以及它们是否应该在同一个系列中。

If you have something like this 如果你有类似的东西

for(MyObj o : array) {
   if(o instanceof A) {
      ((A)o).doA();
   }
   if(o instanceof B) {
      ((B)o).doB();
   }
}

consider this instead 考虑一下这个

abstract class MyObj {
    abstract void doIt();
}

class A {
    void doIt() { doA(); }
}

class B {
    void doIt() { doB(); }
}

Expose the method in the superclass, and then use overriding. 在超类中公开该方法,然后使用重写。 Provide an empty implementation in the base class so that subclasses can ignore the action if needed. 在基类中提供一个空实现,以便子类可以在需要时忽略该操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM