Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

avoiding instanceof

I have a set of POJOs with a common superclass. 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?

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"

like image 843
user28061 Avatar asked Dec 12 '22 00:12

user28061


2 Answers

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!");
        }
    });
}
like image 63
Sergey Kalinichenko Avatar answered Dec 31 '22 09:12

Sergey Kalinichenko


If you know they're of the subclass type, then just cast them directly without an instanceof check.

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).

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.

like image 30
Louis Wasserman Avatar answered Dec 31 '22 10:12

Louis Wasserman