views:

499

answers:

4

I have a baseclass, Statement, which several other classes inherit from, named IfStatement, WhereStatement, etc... What is the best way to perform a test in an if statement to determine which sort of Statement class an instance is derived from?

+7  A: 
if (obj.getClass().isInstance(Statement.class)) {
   doStuffWithStatements((Statement) obj));
}

The nice thing about this technique (as opposed to the "instanceof" keyword) is that you can pass the test-class around as an object. But, yeah, other than that, it's identical to "instanceof".

NOTE: I've deliberately avoided editorializing about whether or not type-instance-checking is the right thing to do. Yeah, in most cases, it's better to use polymorphism. But that's not what the OP asked, and I'm just answering his question.

benjismith
Why not just use the simpler instanceof check?
Steve Kuo
instanceof is not evil like goto. There is a reason it was added to the language and why it has not been deprecated.
David Taylor
+15  A: 
if(object instanceof WhereStatement) {
   WhereStatement where = (WhereStatement) object;
   doSomething(where);
}

Note that code like this usually means that your base class is missing a polymorphic method. i.e. doSomething() should be a method of Statement, possibly abstract, that is overridden by sub-classes.

Dave Ray
Thanks for the additional info! I'll look into it to see if there is a clean way to improve the design.
Heat Miser
+5  A: 

The answer to your question is instanceof.

However, keep in mind that if your code needs instanceof, it's a sign that something is not right with your design. There are some cases when instanceof is justified, but they are rather exceptions. Usually, if your subclasses need to behave differently, you have to use polymorphism instead of if()s.

Igor Krivokon
The only thing I would add to your commend is the strong suggestion of programming by interface.
monksy
+1  A: 

This is not the way to do things in an object-oriented way, it's a throwback to the old code/data dichotomy. Now that's not necessarily a bad thing (if you know what you're doing) but it should be left to the non-object-oriented languages like C.

With proper design, you don't need that sort of behavior. Instead of the construct:

if (obj.getClass().isInstance(Statement.class)) {
    doStuffWithStatements((Statement) obj));
}

(apologies to benjismith for 'stealing' his code), you should really be making the object itself responsible for its own activities thus:

obj.doStuff();

Then each different obj class will have its own definition for doStuff. That is the right way to do it.

paxdiablo