I just decided to write a message regarding the myth that the use of
the instanceof keyword is categorically bad. Not all java programmers
have fallen prey to the myth, but after years on the newsgroups it has
almost gotten to the point where if it was discovered that you used
instanceof anywhere in your app, it *must* be because you have a poorly
designed system.
On these newsgroups? I've followed these newsgroups for many years
(since about 1998) and haven't gotten that impression. Nevertheless, if
the impression has been given, then it is incorrect.
What has often been said is that avoiding runtime type dependencies in
general is a good idea whenever possible. Typically, though, this
advice is applied to reflection instead of use of the instanceof
keyword. I can also see that there are a lot of places where someone
unfamiliar with OO programming may wish to use instanceof, but which
should be replaced with polymorphism. Again, though, I see no
justification for an absolute rule forbidding instanceof. Indeed,
inheritance is often poorly applied to situations where it breaks proper
separation of concerns.
It has been said that, in most cases, instanceof should not be used to
test for object equality (see [BLEWITT1]) as it can break the symmetric
property of the equals method's equivalence relation. In this case,
using the getClass method of Object is the appropriate choice. This
makes a lot of sense.
I am completely with you on this one. I have noticed a tendency (not so
much on this newsgroup, but in other places, at least, such as
introductory textbooks of fly-by-night tutorial web sites that are
sometimes posted here) to do the following:
1. Assume that the programmer intends to write a certain kind of very
mechanical implementation of the equals or hashCode methods.
2. Draw conclusions about how to uphold their contracts, on the basis of
these mechanical implementations.
3. Forget that less mechanical implementations are possible.
This tendency is exaggerated by the section (which is a good one, by the
way) in Josh Bloch's Effective Java that gives a mechanical way to
handle hashCode (but that *also* notes that it only applies to
information that is relevant to object identity... a qualification that
is often lost in translation), and by the kinds of silly introductory
examples to overriding hashCode and equals that are frequently in intro
textbooks or tutorials.
An excellent example of where this does NOT apply is java.util.List.
The contract for java.util.List.equals contains a requirement that any
List should compare equal to any other List with the same contents. I
think this is a very poor requirement, but it is nevertheless a
requirement. Beginning an implementation of MyList.equals by comparing
this.getClass() to other.getClass() is a sure-fire guarantee of breaking
the contract.
What is true, though, is that in the absence of some specification for
how to declare dissimilar classes, the task shoulod be considered
impossible... i.e., they should always be considered unequal. That
specification logically ought to occur in the documentation of some
supertype. Hence, it may be valid to say that instanceof should never
be used to check equals UNLESS there is some specification in some
supertype that defines equality for some containing inheritance sub-
hierarchy.
Another thing you may find on the net are people who will try their
darndest to provide you with an example of how you can get around using
instanceof. They will explain that you need their complex, difficult
to maintain, cyclic-dependency-creating solutions because your design
is bad (you used instanceof right?... so it *must* be bad), and that
your solution will certainly be a nightmare to maintain in the future.
Hopefully, you don't mean to include here situations in which someone
provides not only general advice on how to avoid using instanceof, but
also specific negative consequences of the use of instanceof, and how
their proposed solutions avoids those drawbacks. For example, one
common problem with instanceof is that it introduces a single point that
must be extended in order to completely integrate a new subtype into the
system. If the solution can avoid this by moving certain type-specific
code into the subclass itself, this is nearly always a good thing.
Therefore, there is reason to be cautious with this keyword when working
in a situation where the list of possible subtypes is not theoretically
limited, such as when working with a hierarchy of objects representing
different accounting policies for various legal jurisdictions.
Use method overloading instead
==============================
Visitor (and Proxy Visitor)
===========================
You missed the obvious one. If possible, take the type-specific
behavior, and move it into a polymorphic method of the class. Doing so
can require some creativity in design... but that's because you're
really doing design rather than following someone's furmulaic answer.
Design is a creative process. It involves finding and using the
abstractions that are inherent to the system.
My suspicion is that when most advice is given to avoid instanceof, this
is what is meant. Don't use instanceof, but rather identify and
describe the inherent abstractions that allow you to write something
that applies to all relevant types. If the advice is taken to mean
something else, such as that a specific trick should be employed to
remove the keyword in an automatable way, then someone has profoundly
missed the point.
Other people using instanceof
=============================
Note that most of the really good examples of using instanceof come from
writing code that is inherently somewhat dynamic systems. The only
exception I can think of comes from so-called "marker" interfaces, which
are problematic from a design standpoint anyway; or from backward-
compatibility limitations that prevent making appropriate changes to a
common supertype.