"Chris Uppal" <> wrote in message
news:ws2dnVg3jbRIDg3cRVn-...
> DeMarcus wrote:
>
> > What's the common opinion about using the java keyword
> > instanceof?
>
> I don't disagree with the previous replies that I've seen, but I wanted to
give
> a slightly different spin to the answer.
>
> Think of it this way: the system (Java's semantics and OO in general) is
> designed so that objects are responsible for their own behaviour. That's to
> say that it's /their/ responsibility to know "what they are" and what they
> should do in any specific circumstance. If you use instanceof then you are
> cutting them out of the loop. In effect you are saying, "no, I don't care
what
> you think, I'm going to do this /my/ way".
>
> Now that's fine if you know what you are doing and have a good reason. But
you
> are also throwing away the modularity, flexibility, comprehensibility, and
> maintainability that were the point of using OO in the first place.
>
> You can think of 'instanceof' as a specific kind of reflection. Other
examples
> of reflection are the facilities in java.lang.reflect for looking at what
> methods and fields are available, and the use of finalize() to reflect on an
> object's lifetime. These features allow you more power and control over the
> way the system works, but at the cost that /you/ have taken over
responsibility
> for some aspect of the operation that the system would otherwise look after
for
> you. Reflection in general is something that "ordinary" programs don't, and
> shouldn't, make much use of. (Although, as Chris Smith noted, it does depend
> on how dynamic a programming environment / language you are working with[*])
> In general, even if you do need to use reflection (and 'instanceof'
> specifically) to make some design work, then it won't be as ad-hoc hacks
> scattered randomly around the system. You'd be able to look at the design in
> advance and say (after some thought) "we'll need to use reflection <here> and
> <here>, there's no need for it anywhere else".
>
> And I think that's the point: if you are just scattering 'instanceof' around
in
> an arbitrary way (if a reader can't look at what a method does and reliably
> guess whether you'd use 'instanceof' before reading your code) then you are
> almost certainly creating an ugly mess of hacks.
>
> BTW, there's nothing /inherently/ wrong with slimy hacks. Sometimes you can
> use a well-placed hack to gather all the ugliness of (part of) a system into
> one place and hide it where it doesn't affect everything else. You'll be able
> to recognise such uses quite easily since there will be a long comment
> apologising for the hack, and explaining why it's better than the alternatives
> in this case.
/snip/
I agree. Using "instanceof" is similar to using a switch block
with some kind of "type code" thing that distinguishes the actual
type. The general rule of OOP is that such constructs should be
replaced with polymorphism where possible. In the case of external
non-OO data, a switch block is necessary for creating the initial
object with an appropriate subtype.
I've used "instanceof" mostly in places where I was too lazy
to do it the right way. For example, an ArrayList that has both
JPanel and JLabel instances, I would use "instanceof" to distinguish
and downcast the next instance that I pulled from the ArrayList. It
was simple, it worked, and the ArrayList was very private. There was
no way that the "instanceof" usage could spread through-out the
application.
For a more flexible approach, I use something like this:
=========================================
public class Fubar
{
public void doGork(final Gork gork)
{
/* I want to do something with a Gork
that depends on the actual subtype
of Gork. */
gork.invoke(this);
}
public void doSomething(final Snafu snafu)
{
/* Snafu is a subtype of Gork. */
}
public void doSomething(final Gecko gecko)
{
/* Gecko is a subtype of Gork. */
}
}
public abstract class Gork
{
public abstract void invoke(Fubar fubar);
}
public class Snafu
extends Gork
{
public void invoke(final Fubar fubar)
{
/* calls Fubar.doSomething(Snafu) */
fubar.doSomething(this);
}
}
public class Gecko
extends Gork
{
public void invoke(final Fubar fubar)
{
/* calls Fubar.doSomething(Gecko) */
fubar.doSomething(this);
}
}
=========================================
This is a form of reflection that uses
overloading to distinguish the actual
subtype of Gork that was passed to
Fubar.doGork(Gork).
Since Fubar must know all of the subtypes of
Gorko (which it must know anyway when using
instanceof), this technique avoids instanceof
and achieves the same effect of distinguishing
the actual subtype of Gork on behalf of
Fubar.doGork(Gork).
A little imagination can extend this technique
to many subtypes of Gork by just adding the
appropriate overloaded "doSomething" method to
Fubar, and defining the new subtype of Gork with
the "invoke(Fubar)" method.
Notice that even though the "invoke" methods in
each of the subclasses are textually the same, their
effect is very different from each due to the usage
of "this" in the method call, which distinguishes
which overloaded "doSomething" method is called. You
would not want to refactor these methods to the parent
abstract class (do you see why?).
This is a very clean usage of polymorphism that
avoids "instanceof" and clearly separates the
work that Fubar.doGork(Gork) wants to perform on
the actual subtype of Gork.
--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS for FREE!