Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2005

Tip: Looking for answers? Try searching our database.

Why should use of instanceof be avoided

Thread view: 
HalcyonWild - 17 May 2005 13:51 GMT
Hi,

I read in a magazine (Dev IQ) that finding out the type of object at
runtime is not a good practice. If you are using instanceof a lot, then
your object model should be reviewed. The design of your application
should be changed. I assume the case goes with reflection also.

Why is this so. If anybody has any idea, please share your views.

Thanks.
Antti S. Brax - 17 May 2005 14:01 GMT
Halcyon.Wild@gmail.com wrote in comp.lang.java.programmer:
> I read in a magazine (Dev IQ) that finding out the type of object at
> runtime is not a good practice. If you are using instanceof a lot, then
> your object model should be reviewed. The design of your application
> should be changed. I assume the case goes with reflection also.

    This is not a new subject. Search Google.

    One of the obvious reasons is that every time you use
    instanceof you are hardcoding a class name.

Signature

Antti S. Brax                  Rullalautailu pitää lapset poissa ladulta
http://www.iki.fi/asb/         http://www.cs.helsinki.fi/u/abrax/hlb/

              [1385 messages expunged from folder "Spam"]

HalcyonWild - 17 May 2005 14:32 GMT
>     One of the obvious reasons is that every time you use
>     instanceof you are hardcoding a class name.

I searched google before posting this. Opened the links on the first
few pages. What I found is this:
1. There are some pages which say use of instanceof is ok(javaworld
actually says its good to use instanceof before attempting casting),
and some which say it should be avoided.
2. None of them say hardcoding a class name is the reason.
3. One of them even goes on to say avoid casting, in its list of best
practices.
4. A page from MIT said it indicates clumsy structuring. Not very
enlightening.

One page which I found said that more use of instanceof indicates
poorly designed classes with insufficient use of polymorphism.

What about a scenario where in you want to take different actions on
different subclasses, say SubClass1 and SubClass2, and you are passed
the parent of these two subclasses as parameter in your method. You
have to check which subclass it is exactly. I am using
polymorphism/inheritance here, since I get the parent class.

Where does the wrong design thing come in. The article I originally
read had just a single line on this topic.
Bjorn Abelli - 17 May 2005 14:52 GMT
"HalcyonWild" wrote...

> I searched google before posting this. Opened the links on the first
> few pages. What I found is this:

> 1. There are some pages which say use of instanceof is ok(javaworld
> actually says its good to use instanceof before attempting casting),
> and some which say it should be avoided.

But that's because you otherwise can get a ClassCastException...

It's even better to avoid explicit casting at all, if you can...

> 2. None of them say hardcoding a class name is the reason.

Well, hardcoding a class name just to make specific actions depending on
class is best to avoid.

Instead it's better to delegate the actions to the classes themselves
(polymorphism).

> 3. One of them even goes on to say avoid casting,
> in its list of best practices.

As I said above... ;-)

> 4. A page from MIT said it indicates clumsy structuring.
> Not very enlightening.

Which means just the same as above, recommending more ploymorphism...

> One page which I found said that more use of instanceof
> indicates poorly designed classes with insufficient use
> of polymorphism.

p4.

> What about a scenario where in you want to take different
> actions on different subclasses, say SubClass1 and SubClass2,
> and you are passed the parent of these two subclasses as
> parameter in your method. You have to check which subclass
> it is exactly. I am using polymorphism/inheritance here, since
> I get the parent class.

No, you're not really using the "Polymorphism pattern" (look up GRASP), as
you even need to know which subclass it is.

The object know which class it is, so behaviour depending on which class it
is, should be delegated to the object itself.

// Bjorn A
Paul Tomblin - 17 May 2005 15:14 GMT
In a previous article, "HalcyonWild" <Halcyon.Wild@gmail.com> said:
>What about a scenario where in you want to take different actions on
>different subclasses, say SubClass1 and SubClass2, and you are passed
>the parent of these two subclasses as parameter in your method. You
>have to check which subclass it is exactly. I am using
>polymorphism/inheritance here, since I get the parent class.

If you want action "foo" to happen in SubClass1 and action "bar" to happen
in SubClass2, then the parent class should provide a method which SubClass
overrides to do "foo" and SubClass2 overrides to do "bar'.  Then you don't
have "instanceof" calls, although the converse is that if you're doing
this too much you end up with bazillions of little action methods that do
very little.

Signature

Paul Tomblin <ptomblin@xcski.com> http://xcski.com/blogs/pt/
I think I have a new personal rule: Never watch anything which includes
the author's name in the title, particularly if the author is dead.
             -- Andrew Dalgleish

Thomas Weidenfeller - 17 May 2005 15:19 GMT
>>    One of the obvious reasons is that every time you use
>>    instanceof you are hardcoding a class name.
>
> I searched google before posting this. Opened the links on the first
> few pages. What I found is this:

instanceof is some kind of programmer's duct tape. You should try to
avoid it, and use real nuts and bolts in your code, but if you can't
avoid it you are glad that you have it.

In practice, this means if the design of some new code relies on
instanceof you should better think twice and look for other solutions.
If you have to "somehow" interface to existing code out of your control,
instanceof can be the thing that saves you.

> 1. There are some pages which say use of instanceof is ok(javaworld
> actually says its good to use instanceof before attempting casting),

IMHO you interpreted this in the wrong way. I bet, the javaworld author
said or wanted to say:

    If(!) you are about to cast an object of totally unknown type,
    it is a good idea to check with instanceof first. This way you
    can avoid having to deal with the class cast exception.

This is indeed one of these duct tape things. One is usually unsure of
the real type of an object if it is created by some part (library, etc.)
of the application outside of the own control. So you somehow figure out
the real type, and then you cast to it - but, as a safeguard you better
check.

If you are unsure of the type of an object in your own code, you better
revise your own code, instead of adding safeguards.

> and some which say it should be avoided.

I am in that camp.

> 2. None of them say hardcoding a class name is the reason.

It is one of the things which makes instanceof impractical.

> 3. One of them even goes on to say avoid casting, in its list of best
> practices.

Which is indeed good advice. Unfortunately the standard API and classes
often force you to do some casting. This got better with Java 1.5 where
e.g. the casting needed for the collection classes can be replaced by
using generics.

Still, in your own code avoiding casting is a good idea.

> 4. A page from MIT said it indicates clumsy structuring. Not very
> enlightening.

They are right. It is exactly that. If you feel the need to use an
instanceof in your code, some little alarm bell in your head should ring
and you should investigate your code for a better solution.

> One page which I found said that more use of instanceof indicates
> poorly designed classes with insufficient use of polymorphism.

Yes, again they are right. Making use of polymorphism is often a better
design alternative to using an instanceof. Using instanceof in fact
often indicates that the programmer didn't get OO programming very well.

> What about a scenario where in you want to take different actions on
> different subclasses, say SubClass1 and SubClass2, and you are passed
> the parent of these two subclasses as parameter in your method.

Bzzzz, game over, you lost.

(1) Instead of

    void myMethod(Superclass o) {
        if(o instanceof SubclassA) {
            // do something specific for SubclassA
        } else if(o instanceof SubclassB) {
            // do something specific for SubclassB
        }
    }

you write (2)

    void myMethod(SubclassA o) {
        // do something specific for SubclassA
    }

    void myMethod(SubclassB o) {
        // do something specific for SubclassB
    }

(3) Or, sometimes it makes more sense to implement the particular method
as part of the object itself, overriding a Superclass method:

    void myMethod(Superclass o) {
        o.doSomething();
    }

> You
> have to check which subclass it is exactly.

No, you leave this to the compiler.

> I am using
> polymorphism/inheritance here, since I get the parent class.

You use dynamic polymorphism with static type checking. Already the
usage of the two words "dynamic" and "static" in the same sentence
should ring a bell. Using a separate method for each subtype (2) fixes
the problem with ad-hoc polymorphism (overloading). Using overridden
methods and double-dispatch (3) is another possible fix.

> Where does the wrong design thing come in.

From your idea that you, yourself absolutely have to check the type of
an object if you need to do some type-specific operation on that object.

/Thomas

Signature

The comp.lang.java.gui FAQ:
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq

Dale King - 18 May 2005 06:22 GMT
> Bzzzz, game over, you lost.
>
[quoted text clipped - 17 lines]
>         // do something specific for SubclassB
>     }

That is not really equivalent. Consider if I have this calling code:

   // someMethod returns SubclassA or SubclassB instances
   Superclass x = someMethod();
   myMethod( x );

Will the correct method be called? No, in fact the code won't compile.
While the choice of which class' *overridden* method to call is based on
the runtime type of the object, the choice of which *overloaded* method
to call is based solely on the compile-time types of the arguments.

Your solution will only work if every caller knows the type of the object.
Signature

 Dale King

Thomas Weidenfeller - 18 May 2005 08:09 GMT
> That is not really equivalent.

It is not equivalent, but good enough for the sake of the discussion.

/Thomas

Signature

The comp.lang.java.gui FAQ:
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq

Dale King - 21 May 2005 07:38 GMT
>> That is not really equivalent.
>
> It is not equivalent, but good enough for the sake of the discussion.

Except that the poster gave a scenario where instanceof was used and you
gave him a solution for a completely different problem. Not only is it
not equivalent, it was irrelevant.

One pattern that addresses what he was saying where you are given the
superclass reference and must do something different based on the actual
subclass is the visitor pattern.

Signature

 Dale King

shakah - 17 May 2005 15:27 GMT
[...stuff deleted...]
> What about a scenario where in you want to take different actions on
> different subclasses, say SubClass1 and SubClass2, and you are passed
[quoted text clipped - 4 lines]
> Where does the wrong design thing come in. The article I originally
> read had just a single line on this topic.

The basic idea is that rather than the following:
 public abstract class MyShape {
 }

 public class MySquare extends MyShape {
   public float fEdgeLength_ ;
 }

 public class MyCircle extends MyShape {
   public float fRadius_ ;
 }

 public class YourClass {
   public float calcArea(MyShape s) {
     if(s instanceof MySquare) {
       return ((MySquare) s).fEdgeLength_ * ((MySquare)
s).fEdgeLength_ ;
     }
     else if(s instanceof MyCircle) {
       return 3.14159f * ((MyCircle) s).fRadius_ * ((MyCircle)
s).fRadius_ ;
     }
     return 0.0f ;
   }
 }

it is better to do something like:
 public abstract class MyShape {
   public float calcArea() ;
 }

 public class MySquare extends MyShape {
   private float fEdgeLength_ ;
   public float calcArea() {
     return fEdgeLength_ * fEdgeLength_ ;
   }
 }

 public class MyCircle extends MyShape {
   private float fRadius_ ;
   public float calcArea() {
     return 3.14159f * fRadius_ * fRadius_ ;
   }
 }

 public class YourClass {
   public float calcArea(MyShape s) {
     return s.calcArea() ;
   }
 }
John C. Bollinger - 17 May 2005 15:43 GMT
>>    One of the obvious reasons is that  every time you use
>>    instanceof you are hardcoding a class name.
[quoted text clipped - 4 lines]
> actually says its good to use instanceof before attempting casting),
> and some which say it should be avoided.

There are cases in which casting is unavoidable and in which you cannot
be confident that the object to be cast is in fact of the type you want.
    Implementation of an equals(Object) method is a good example.  In
these cases, instanceof is pretty much indispensable.  Note well,
however, that even here, the need for instanceof is construed by many as
a language wart.

> 2. None of them say hardcoding a class name is the reason.

Well what reasons do they give, then?  It seems that would be a fair
place to start the discussion.  The need to hardcode a class name _is_ a
good reason to avoid instanceof, particularly when the class name in
question is not that of the class in which the name is to be used.

More generally though, relying on instanceof is generally a sign of poor
OO practices.  The _declared_ type of an Object should be sufficient for
your program's use within the scope of that declaration.  If it isn't,
then you need either a more specific declaration or a better design for
the class / interface corresponding to the declared type.

This is not just theoretical.  A program that relies on run-time type
information is often brittle relative to a similar program that does
not.  The former does not usually adapt well to new classes being added,
and it can be a real mess to determine what a method can, should, or
will do without deep analysis of program flow.

> 3. One of them even goes on to say avoid casting, in its list of best
> practices.

Absolutely.  That goes along with my comments above.  It was much harder
to do that before Java 1.5, but now, with proper use of Generics, a
well-written program can avoid most casts.

> 4. A page from MIT said it indicates clumsy structuring. Not very
> enlightening.

I suspect that it was referring again back to the same OO issues that I
raised.  You should not need to know anything more specific about an
object's type than the applicable type declaration tells you.  That
could be taken as a minimalist definition of polymorphism.

> One page which I found said that more use of instanceof indicates
> poorly designed classes with insufficient use of polymorphism.

Yes.  Once again the same thing.

> What about a scenario where in you want to take different actions on
> different subclasses, say SubClass1 and SubClass2, and you are passed
> the parent of these two subclasses as parameter in your method. You
> have to check which subclass it is exactly. I am using
> polymorphism/inheritance here, since I get the parent class.

If you cannot reasonably give the appropriate SubClass1 and SubClass2
methods the same name, arguments, and return type, then either your
class hierarchy is messed up or your method is ill-conceived.  You are
NOT correctly using polymorphism here; if you were, then you would not
say that you want to "take different actions on different subclasses".
Read that again, because it is KEY to using polymorphism effectively.

> Where does the wrong design thing come in. The article I originally
> read had just a single line on this topic.

Once again, the same thing.

Signature

John Bollinger
jobollin@indiana.edu

Eric Sosman - 17 May 2005 18:34 GMT
>>> [quoting someone else]
>>>    One of the obvious reasons is that  every time you use
[quoted text clipped - 9 lines]
> good reason to avoid instanceof, particularly when the class name in
> question is not that of the class in which the name is to be used.

   Is the need to hard-code a class name also a good reason
to avoid `new'?

   There are good reasons to minimize the use of `instanceof',
but IMHO "avoiding hard-coded class names" is not among them.

Signature

Eric.Sosman@sun.com

John C. Bollinger - 17 May 2005 20:15 GMT
>     Is the need to hard-code a class name also a good reason
> to avoid `new'?

It is the *only* reason I see to actively avoid 'new'.  You can employ
factory classes, and, to a lesser extent, factory methods to reduce the
number appearances of class names in your code and the impact of naming
classes specifically when you create objects.  In many cases this is
very much overkill, however.

It is considerably more reasonable to tie creation of an object to a
specific, hard-coded class name than it is to tie program logic to the same.

>     There are good reasons to minimize the use of `instanceof',
> but IMHO "avoiding hard-coded class names" is not among them.

As you like.  I have no particular investment in my opinion on the
matter, and so no special interest in trying to persuade you to change
yours.

Signature

John Bollinger
jobollin@indiana.edu

Ross Bamford - 17 May 2005 16:25 GMT
> What about a scenario where in you want to take different actions on
> different subclasses, say SubClass1 and SubClass2, and you are passed
> the parent of these two subclasses as parameter in your method. You
> have to check which subclass it is exactly. I am using
> polymorphism/inheritance here, since I get the parent class.

I would make the 'parent' an interface. Not necessarily *the* interface,
mind you (i.e. it could be a specialised interface that your object
implements among other things). What I mean is you don't have to have
'MyObjectInter' and 'MyObjectImpl'.

If you have subclasses that provide different methods depending on type,
and you need to call those from /above/ in the hierarchy, your design is
broken. Your design isn't Object Oriented, it's just written as Objects.
So you might have a 'DataEater' class, which has a method that swallows
data, and two subclasses, 'CachingEater' and 'BitBucketEater'. Each of
these will have it's own methods (flushcache(), kickbucket(), etc), and
that is fine. Wherever you need to access them, you pass in the actual
type.

The whole point of Encapsulation, though, is that if I'm given a
DataEater I can blindly give it by data and expect it to be eaten.
Contrast this with:

public cacheOrKickEater(DataEater eater) {
 if (eater instanceof CachingEater)
   ((CachingEater)eater).flushCache();
 else
   ((BitBucketEater)eater).kickBucket();
}

In the context of the points above, you see how unnatural this is. It's
is written with Objects, but it's not really OOP.

(n.b. this is not working code, it would likely generate cast
exceptions, especially when you extended your hierarchy).

Ross

Signature

  [Ross A. Bamford]     [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@the.website.domain

Knute Johnson - 17 May 2005 17:11 GMT
>>    One of the obvious reasons is that every time you use
>>    instanceof you are hardcoding a class name.
[quoted text clipped - 21 lines]
> Where does the wrong design thing come in. The article I originally
> read had just a single line on this topic.

It's in the language and it isn't going to go away so use it if you need
it.  If it makes your program easier to read or quicker to code who
really cares?

Signature

Knute Johnson
email s/nospam/knute/

Antti S. Brax - 18 May 2005 07:21 GMT
nospam@sagebrush.frazmtn.com wrote in comp.lang.java.programmer:
> It's in the language and it isn't going to go away so use it if you need
> it.  If it makes your program easier to read or quicker to code who
> really cares?

    And who cares if it makes your program a nightmare to maintain?

    You will as soon as you meet code that has been written by
    someone else who thinks like you. :-)

Signature

Antti S. Brax                  Rullalautailu pitää lapset poissa ladulta
http://www.iki.fi/asb/         http://www.cs.helsinki.fi/u/abrax/hlb/

              [1385 messages expunged from folder "Spam"]

Michael Rauscher - 18 May 2005 08:23 GMT
Knute Johnson wrote on the usage of "instanceof":

> It's in the language and it isn't going to go away so use it if you need
> it.  

The point is: in which cases does one *need* it?

It's in the language, right. Would you also advise, that a C programmer
should use "goto" just because it's in the language?

In fact, the usage of "instanceof" is not (only) a programming issue or
a matter of coding style. It indicates that one circumvents polymorphism
which in turn indicates the possibility of having problems within the
design. In some way this applies to casts, too.

Therefore the problem isn't the "instanceof" itself. E.g. take a look at
Object#equals. If you override this, you'll have to use "instanceof" and
to cast in most cases. On the other hand, a universal action listener

public void actionPerformed(ActionEvent e ) {
    Object source = e.getSource();
    if ( source instanceof JMenuItem )
        ...
    else if ( source instanceof JButton )
        ...
    else if ( source instanceof JTextField )
        ...
}

is a serious design issue.

Bye
Michael
Lee Weiner - 18 May 2005 01:33 GMT
>What about a scenario where in you want to take different actions on
>different subclasses, say SubClass1 and SubClass2, and you are passed
>the parent of these two subclasses as parameter in your method. You
>have to check which subclass it is exactly. I am using
>polymorphism/inheritance here, since I get the parent class.

Inheritance, yes.  Polymorphism, no.  If you were using polymorphism
correctly, you would have methodA() in SubClass1 and methodA() in SubClass2
and each would know the correct thing to do to its object.

Lee Weiner
lee AT leeweiner DOT org
Betty - 18 May 2005 19:33 GMT
> Halcyon.Wild@gmail.com wrote in comp.lang.java.programmer:
> > I read in a magazine (Dev IQ) that finding out the type of object at
[quoted text clipped - 6 lines]
> One of the obvious reasons is that every time you use
> instanceof you are hardcoding a class name.

I use instance of and don't hardcode a class name!
Antti S. Brax - 19 May 2005 10:50 GMT
lisa@nospam.invalid wrote in comp.lang.java.programmer:
>> One of the obvious reasons is that every time you use
>> instanceof you are hardcoding a class name.
>
> I use instance of and don't hardcode a class name!

    So why can't I see you do it?

Signature

Antti S. Brax                  Rullalautailu pitää lapset poissa ladulta
http://www.iki.fi/asb/         http://www.cs.helsinki.fi/u/abrax/hlb/

              [1385 messages expunged from folder "Spam"]

Fred L. Kleinschmidt - 17 May 2005 22:22 GMT
> Hi,
>
[quoted text clipped - 6 lines]
>
> Thanks.

Many responders have pointed out some of the reasons to minimize the us
of instanceof, but there are many times when it is your friend.

Consider a GUI application that needs to determine the Window (or
Dialog, or Frame, etc.) ancestor of a GUI component. The easiest way is
to walk the parent tree up until finding a parent that is "instanceof
Window".

Signature

Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Common User Interface Services
M/S 2R-94  (206)544-5225

Anton Spaans - 17 May 2005 23:09 GMT
> Hi,
>
[quoted text clipped - 6 lines]
>
> Thanks.

From the arguments in the previous posts, it is best to avoid casts and
instanceof statements as much as possible.
But sometimes it can have its use.

One situation is the use of so-called 'Marker Interfaces'. An example is
java.io.Serializable.
Such an interface does not declare any methods. Instead it declares a
contract between objects implementing the marker-interface and the users of
such objects and this type of contract can not be expressed with
declarations, using java syntax.

As an example:  how would one express the contract of java.io.Serializable
in plain java-code? (the contract stating - in short - that objects
implementing java.io.Serializable must have members that are either
serializable as well or that are volatile)

The user of objects implementing marker-interfaces make use of the
instanceof statement.

What do you all think about using these marker-interfaces?

URL to definition: http://tinyurl.com/djr49
-- Anton.
John C. Bollinger - 18 May 2005 16:02 GMT
> From the arguments in the previous posts, it is best to avoid casts and
> instanceof statements as much as possible.
[quoted text clipped - 16 lines]
>
> What do you all think about using these marker-interfaces?

I do not much care for marker interfaces in general.  Most uses of such
interfaces fall right along the lines of the preceding discussion.
Markers can occasionally be useful without reliance on instanceof,
however.  Consider Serializable for example, and ignore Generics: if I
want to ensure that a Serializable class really can be serialized
successfully, then I cannot  give it non-static, non-transient,
non-Serializable member variables, including variables of type Object.
In this case, the most general type with which I can safely declare
variables is Serializable.  Similarly, if I write a general-purpose
method that accepts a reference and attempts to serialize the
corresponding object, then the most general type I can safely assign to
the parameter in question is Serializable.

My opinion in general is that use of a class or interface that is based
on declaring it as the *type* of a reference is pure, good, and
enlightened (at the very abstract level of this discussion) whereas use
of a class or interface involving testing it against the *class* of a
reference is a dabbling with the dark side.

Signature

John Bollinger
jobollin@indiana.edu

Dale King - 21 May 2005 07:48 GMT
>> From the arguments in the previous posts, it is best to avoid casts and
>> instanceof statements as much as possible.
[quoted text clipped - 37 lines]
> of a class or interface involving testing it against the *class* of a
> reference is a dabbling with the dark side.

I'm not sure that Sun agrees with you here. The marker interface concept
is now basically supplanted by annotations. Checking of runtime
annotations is conceptually little different than using instanceof.

Signature

 Dale King

John C. Bollinger - 23 May 2005 14:52 GMT
>> My opinion in general is that use of a class or interface that is
>> based on declaring it as the *type* of a reference is pure, good, and
[quoted text clipped - 5 lines]
> is now basically supplanted by annotations. Checking of runtime
> annotations is conceptually little different than using instanceof.

Sun may indeed not agree with me here, but I don't find that persuasive
in itself.  There does seem to be quite a lot to annotations that
doesn't involve RTTI (-like) behavior, so I'm not prepared to throw out
the whole thing.  I haven't really studied the annotation system well
enough to form firm opinions of it, however.

Signature

John Bollinger
jobollin@indiana.edu

Wibble - 18 May 2005 02:18 GMT
I think avoiding hardcoding of class names is a silly reason not to use
instance of.  The reason not to use it is because objects should
describe thier own behavior.  If you move all the behavior out of the
object into scattered instanceof's, then its very hard to figure out
what the object actually does.  The reason instanceof is fine in an
equals method, is that its looking for an instance of the current
class, still describing its own behavior.

> Hi,
>
[quoted text clipped - 6 lines]
>
> Thanks.
HalcyonWild - 18 May 2005 11:46 GMT
Hi all,
First of all, Thanks a lot to all of you. Helped me clear up my
confusion to some extent.
I was trying out examples posted by people on this thread. I picked up
on examples given by Shakah, Thomas Weidenfeller and Dale King, and
worked upon it.

See Listing 1. I was thinking what if it is not possible to have a
common base class for the two subclasses, for example, I decide that
MyCircle and MySquare are two different classes altogether. Now I
create a MyCircle instance and a MySquare instance. And call a local
overloaded getArea() method. Whatever is passed, it recognizes the
correct call, and calls the appropriate class method to calc the area.
Note that passing MyShape instance will not work, in case you pass
MyShape and do not overload getArea() to receive MyShape parameter.
Polymorphism is one way here.

The Listing 2 changes a bit. I added getShape() method which returns
MyShape. Now MyCircle and MySquare are subclasses of MyShape. I do not
know what getShape() will return me. I can very well put MySquare
there, instead of MyCircle. And it works fine.
One dead end. I cannot modify MyCircle properties using the MyShape
ref, like setting the radius (in case i do not use the constructor to
set radius). I would need to know what shape it exactly is, so that I
know I want to change the radius or the length of the shape.

Here is one situation where you would want to use instanceof or
getClass().getName(); Let me know if I am wrong. Also let me know if
you need any clarifications. Sooner or Later, I will get back.

Listing 1.
//save in YourClass.java
public class YourClass {

    public double getArea(MyCircle circle) {
        return circle.calcArea() ;
    }

    public double getArea(MySquare square) {
        return square.calcArea();
    }

    public static void main(String args[])    {
        YourClass y = new YourClass();
        MyCircle circle = new MyCircle();
        MySquare square = new MySquare();
        circle.setRadius(10.0);
        square.setLength(10.0);
        System.out.println(y.getArea(circle));
        System.out.println(y.getArea(square));
    }
}

class MyCircle
{
    private double dRadius_;
    public void setRadius(double r)
    {
        this.dRadius_ = r;
    }
    public double calcArea()
    {
        return (3.14159 * dRadius_ * dRadius_);
    }
}

class MySquare
{
    private double dLength_;
    public void setLength(double l)
    {
        this.dLength_ = l;
    }
    public double calcArea()
    {
        return (dLength_ * dLength_);
    }
}

=====================================

listing 2
public class YourClass {
    public MyShape getShape()
    {
        MyShape shape = new MyCircle(10.0);
        return shape;
    }

    public static void main(String args[])    {
        YourClass y = new YourClass();
        MyShape s = y.getShape();
        System.out.println(s.calcArea());
    }
}

abstract class MyShape {
   public abstract double calcArea() ;
}

class MyCircle extends MyShape
{
    private double dRadius_;
    public MyCircle()
    {
        this.dRadius_ = 0.0;
    }
    public MyCircle(double d)
    {
        this.dRadius_ = d;
    }
    public void setRadius(double r)
    {
        this.dRadius_ = r;
    }
    public double calcArea()
    {
        return (3.14159 * dRadius_ * dRadius_);
    }
}

class MySquare extends MyShape
{
    private double dLength_;
    public void setLength(double l)
    {
        this.dLength_ = l;
    }
    public double calcArea()
    {
        return (dLength_ * dLength_);
    }
}
shakah - 18 May 2005 13:38 GMT
> Hi all,
> First of all, Thanks a lot to all of you. Helped me clear up my
[quoted text clipped - 12 lines]
> MyShape and do not overload getArea() to receive MyShape parameter.
> Polymorphism is one way here.

[...stuff deleted...]

> Listing 1.
> //save in YourClass.java
[quoted text clipped - 44 lines]
>     }
> }

[...more stuff deleted...]

Just addressing your Listing 1 example, and in particular your question
of "what if it is not possible to have a common base class for the two
subclasses". One way to deal with that in Java is to use interfaces,
e.g.:
 public interface MyShape {
   public double calcArea() ;
 }

and changing MyCircle to something like:
 public class MyCircle
   implements MyShape {
     private double dRadius_;
     public void setRadius(double r) { dRadius_ = r; }
     public double calcArea() {
       return (3.14159 * dRadius_ * dRadius_);
     }
 }

 public class MySquare
   implements MyShape {
   [...]
 }

which gets you back to things in YourClass like:
 public double getArea(MyShape s) {
   return s.calcArea() ;
 }

 MyCircle circle = new MyCircle();
 MySquare square = new MySquare();

 getArea(circle) ;
 getArea(square) ;

As you can tell, there are a lot of ways to slice and dice this stuff.
Using polymorphism in general, and interfaces in particular, tends to
be more tolerant of changes down the line. For instance, when a new
shape comes along (e.g. a MyRectangle), in your latest listing 1 you'd
have to add a new method to YourClass which takes a MyRectangle,
whereas in the modification above you'd just make MyRectangle implement
MyShape and everything's good-to-go.
Thomas Weidenfeller - 18 May 2005 14:29 GMT
> The Listing 2 changes a bit. I added getShape() method which returns
> MyShape. Now MyCircle and MySquare are subclasses of MyShape. I do not
> know what getShape() will return me.
[...]

You are using a made-up scenario. Sure, you can't know if you get a
circle or square back from some completely alien method which just
returns shape. However, the point is to try really hard to avoid exactly
this situation. It is not always possible - we have discussed that
already - but you should try.

Let's try to apply some reasoning to your made-up scenario. This might
or might not work in the real world:

(1) Your getShape() method is basically constructed in a way as if any
kind of shape will do for the caller. The method just promises "if you
call me you get some kind of shape". For a caller this is only good
enough, if indeed any kind of shape will do for the purpose of the
caller. However, in your example it turns out it is not good enough. The
caller says "but, but, but ... if I got a circle, I want to set the
radius!".

You see the mismatch? By calling getShape() the caller indicates any
shape will do, but suddenly any shape is no longer good enough for the
caller. So, calling getShape() is already the wrong thing to do. If you
know you need a circle, *don't ask for an arbitrary shape, ask for a
circle*. The simplest way to ask for a circle is to create one:

    MyCircle circleShape = new MyCircle(...);

or implement a specific getCircle method:

    MyCircle circleShape = y.getCircle();
    circleShape.setRadius(10);

(2) If you really need to keep the getShape() method, than one
alternative would be to once again use a double-dispatch to direct each
shape to a shape type specific configuration method:

    abstract class MyShape {
        abstract void config(ShapeConfigurator sc);
    }

    class MyCircle {
        void config(ShapeConfigurator sc) {
            sc.config(this);
        }
    }

    class MyRectangle {
        void config(ShapeConfigurator sc) {
            sc.config(this);
        }
    }

    // Provide shape-specific configuration
    class ShapeConfigurator {
        void config(MyCircle c) { c.setRadius(10); }
        void config(MyRectangle r) { ... }
    }

    class UserShapeConfigurator extends ShapeConfigurator {
        void config(MyCircle c) {
            // Ask user for a new Radius and set it
            ...
            ...
        }
    }

    ShapeConfigurator sc = new UserShapeConfigurator();
    MyShape aShape = y.getShape();
    aShape.config(sc);

There are for sure other architectures possible (e.g. not explicitly
providing a shape configurator), or no configurator at all, and instead
fully implement the config() methods in the shapes. It all depends on
what you really need.

/Thomas

PS: The shape/circle/rectangle/triangel/etc. example is a common one in
OO textbooks (like the pet/animal example). However, it is a dreaded
one, because as you are about to find out, the different basic geometry
shapes have very little in common (that's why the mathematicians settled
on them). There aren't too many properties one can abstract into a
superclass. E.g. even the meaning of some "origin" coordinate in the
superclass is debatable. What's the origin of a circle? Its center?
What's the origin of a triangle? Things which shapes have in common are
mostly representation attributes, like colors, border line style an
thickness, or in short, the ability to be drawn in some way and form.

Signature

The comp.lang.java.gui FAQ:
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq

HalcyonWild - 23 May 2005 16:28 GMT
Hi,
Thanks to everyone for posting. Helped me clear my concepts a lot.

> You are using a made-up scenario. Sure, you can't know if you get a
> circle or square back from some completely alien method which just
> returns shape. However, the point is to try really hard to avoid exactly
> this situation. It is not always possible - we have discussed that
> already - but you should try.

It is a made up scenario but very similar to an actual situation I had
come across in production code of a system running in one of the
world's largest insurance companies.
We have three info objects, Policy, PolicyA and PolicyB. Both PolicyA
and PolicyB are subclasses of Policy. When the user enters a policy
number on the screen, a method is called which retrieves data from DB
and returns a Policy object. Now there is no way of knowing what is
going to be returned, PolicyA or PolicyB.

So we have code like

public doSomethingWithPolicy(String pNumber)
{
 Policy p = policyBean.getPolicyFromDB(pNumber);
 //some code
 if (p instanceof PolicyA)
 {
   //do this
 }
 else (p instanceof PolicyB)
 {
   //do that
 }
 //more code
}

The abstract methods in Policy can be used directly.
I understand that if I have to carry out some operations specific to
PolicyA, on PolicyA, like set the contract end date (ie call PolicyA
specific methods), I would have to use configuration class and call it
through the PolicyA or PolicyB (like the ShapeConfig example).
hawat.thufir@gmail.com - 27 May 2005 12:47 GMT
...
> Things which shapes have in common are
> mostly representation attributes, like colors, border line style an
> thickness, or in short, the ability to be drawn in some way and form.
...

in high school geometry they told me lines don't have a thickness ;)

-Thufir


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.