It seems to me that instanceof
comes from the land of functional programming and is a watered down version of pattern matching and that the OO altenative to it should be dynamic dispatching.
In OO languages (think Ruby), is there any situation where instanceof
is the only solution? I can’t think of any myself, especially in Ruby where you can patch any class with any methods you like.
6
The usual argument for avoiding instanceof
is “Instead of checking the type of a thing to decide on an action, you should make that action a method of that thing, and use inheritance to ensure that every thing automatically does the right thing.” In other words, use the method look-up mechanism built into the language rather than program your own.
However, that usually is restricted to single dispatch: selecting an action based on the exact type of one participant. If there are two or more participants with varying types, it simply doesn’t work, because most languages only have single dispatch built in. You can sometimes rearrange things so that the two participants become arguments to a method on a third one and use method overloading, which does support selection based on several parameter types, but (again, usually) only when the alternatives aren’t subtypes of each other. It may also also be resolved at compile time rather than at run time, which subtly changes the semantics of your program.
That is by no means the only thing that instanceof
makes possible, but in my view the most relevant one.
2
There are situations where instanceof
is unavoidable. This applies to languages, where a class can be closed. For example, in Java there can be final classes. You can’t inherit from them, nor can you make such a class implement an interface of your own.
An example case would be to have a list containing Integer and Double objects and you want to do different things based on the type.
Not really, no. In a language that supports interfaces (either explicitly, or in the form of multiple inheritance with pure virtual classes, like C++), you can always use the following pattern:
interface Fooable {
void foo();
}
abstract class BaseBaz {
public abstract Fooable asFooable();
}
class BazOne extends BaseBaz {
public Fooable asFooable() { return null; } // not a Fooable!
}
class BazTwo extends BaseBaz implements Fooable {
public void foo() { Console.print("I am teh foobar!"); }
public Fooable asFooable() { return this; }
}
// --- snip ---
void runFooOnBaz(Baz baz) {
Fooable fooable = baz.asFooable();
if (fooable == null)
throw new NotFooableException();
fooable.foo();
}
That is, you approach each object by interface, and give the base class a method to return you the object by interface if possible. (There is probably a name for this pattern, but I don’t know it – if anyone knows, feel free to edit.)
In a duck-typing language like Python, you’d go a different route: rather than asking whether the object inherits from a given class, you just pretend it does and prepare for failure:
class BazOne(object):
pass
class BazTwo(object):
def foo():
print "I am teh foobar!"
def runFoo(baz):
try:
baz.foo()
except AttributeError:
raise NotFooableError()
However, the latter isn’t always possible; reasons as to why not include:
- You might rely on more than one method, and the first call has side effects that you cannot allow unless the second method also exists. Inspecting the object instead of having it run into the exception can usually solve this, but it’s not necessarily very pretty.
- You might have to decide on how to treat the object in a way that does not depend on a particular method; for example, you may want to treat
unicode
andstring
objects differently. - The objects might implement a method of the same name, but with different meanings –
hero.save(hostage)
andfile.save(filename)
are completely unrelated things, but the method names happen to collide, so just checking whether a method calledsave
exists can yield false positives.
And then there’s the situation where you have to decide on a code path based on more than one object; you can certainly work your way out using the self-describing method approach, or by testing relevant attributes of all the objects, but sometimes, instanceof
is just easier to write, more readable, and more concise, in other words, the pragmatic choice.
5
While instanceof should be avoided some Java interfaces require it as part of their contract.
For example: javax.security.auth.callback.CallbackHandler.
It defines:
void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
Callback is an interface with no methods so the only way to differentiate different types of Callback objects is using instanceof. The documentation for CallbackHandler.handle() encourages using instanceof.
2