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 / December 2005

Tip: Looking for answers? Try searching our database.

overloading methods

Thread view: 
mabramso@hotpop.com - 09 Dec 2005 20:36 GMT
Right now, if I get an object of a generalized class, for example
Message, I have to do an instanceof to cast the object to a more
specialized class and then call the specialized method with an
appropriate cast. For example:

public void receiveMessage (Message m) {
    if (m instanceof StopMessage)
     parseMessage((StopMessage) m);
    }

Is there a way to get rid of those kindof stub methods and just code
the specialized methods? Those "if" can get pretty unwieldly. I do
have 1.5 but I don't know if generics make a difference there.

Thanks,

myriam
Oliver Wong - 09 Dec 2005 20:56 GMT
> Right now, if I get an object of a generalized class, for example
> Message, I have to do an instanceof to cast the object to a more
[quoted text clipped - 9 lines]
> the specialized methods? Those "if" can get pretty unwieldly. I do
> have 1.5 but I don't know if generics make a difference there.

   AFAIK, no, there isn't. It might help a bit if you actually give all
your "overloaded" methods the same name, e.g.

<code>
public void receiveMessage(Message m) {
 if (m instanceof StopMessage)
   receiveMessage((StopMessage) m);
 }
}
</code>

   but this will only work if, in the calling code, you already knew you
had a StopMessage as opposed to a generic Message.

   You might want to try something like a Visitor pattern, but this might
force your messages to become aware of the classes that handle them.

<code>
abstract class Message {
 public abstract void accept(MessageHandler mh);
}

class StopMessage extends Message {
 public void accept(MessageHandler mh) {
   receiveMessage(this);
 }
}

class GoMessage extends Message {
 public void accept(MessageHandler mh) {
   receiveMessage(this);
 }
}

MessageHandler {
 public void receiveMessage(StopMessage sm) {
   //Do something useful.
 }

 public void receiveMessage(GoMessage gm) {
   //Do something useful.
 }

 public void receiveMessage(Message m) {
   m.accept(this);
 }
}
<code>

   - Oliver
Alex Molochnikov - 09 Dec 2005 21:12 GMT
> <code>
> public void receiveMessage(Message m) {
[quoted text clipped - 3 lines]
> }
> </code>

You must have meant:

   super.receiveMessage((StopMessage) m);

or else your method will cause stack overflow as soon as it receives an
argument of StopMessage class. Alternatively, he will have to implement
receiveMessage(StopMessage method) which will only muddy up the design.

> class StopMessage extends Message {
>   public void accept(MessageHandler mh) {
>     receiveMessage(this);
>   }
> }

Did you mean:

   mh.receiveMessage(this);

in this and other method?

Alex Molochnikov
Gestalt Corporation
Oliver Wong - 09 Dec 2005 21:49 GMT
>> <code>
>> public void receiveMessage(Message m) {
[quoted text clipped - 11 lines]
> argument of StopMessage class. Alternatively, he will have to implement
> receiveMessage(StopMessage method) which will only muddy up the design.

   I meant this latter "Alternatively, etc.". I had assumed the OP had
intended to define multiple methods of the same name since the subject line
was "overloading methods".

>> class StopMessage extends Message {
>>   public void accept(MessageHandler mh) {
[quoted text clipped - 7 lines]
>
> in this and other method?

   Yes, sorry.

   - Oliver
Patrick May - 09 Dec 2005 22:38 GMT
> Right now, if I get an object of a generalized class, for example
> Message, I have to do an instanceof to cast the object to a more
[quoted text clipped - 5 lines]
>      parseMessage((StopMessage) m);
>     }

    Are you always calling a method with the same signature
regardless of the particular message subtype?  If so, why do you need
to know the subtype in receiveMessage()?

    In general, having to perform type identification at run time is
a "code smell" that indicates you should be using a different
approach.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc.    | The experts in large scale distributed OO
                        | systems design and implementation.
         pjm@spe.com    | (C++, Java, Common Lisp, Jini, CORBA, UML)
mabramso@hotpop.com - 12 Dec 2005 16:11 GMT
Thanks for the pointer. The ChainOfResponsibility pattern seems like
the way to go. The reference to common lisp is also appropriate since
in CLOS, there is no such problem. But CLOS has dynamic binding much
like Nice as pointed out by Roedy.

Thanks to all who answered and happy holidays!

Signature

                                  myriam

Abhijat Vatsyayan - 10 Dec 2005 02:18 GMT
What kind of control do you have on these classes? Can you change the
message class hierarchy? If you need to do different handling based on
the runtime type of object "m" (input to receiveMessage) , then it has
to be coded *somewhere*. If possible, you could probably change the
Message class/interface to support a getType()  .. which can be used
with a MessageProcessorLocator to locate a Processor.

Message
{
    public MessageType getType() ;
}
MessageProcessorLocator
{
    MessageProcessor locateProcessor(MessageType type) ;
}
MessageProcessor
{
    void  processMessage(Message msg) ;
}
StopMessageProcessor implements MessageProcessor
{

}
You can then maintain a map of MessageProcessors in the locator object
keyed using the message types.
Locator object can use this map to locate message processors.
If you implement your Map and Locator properly, you will not have to
worry about ugly "if" or switch constructs.
Abhijat

> Right now, if I get an object of a generalized class, for example
> Message, I have to do an instanceof to cast the object to a more
[quoted text clipped - 13 lines]
>
> myriam
zero - 10 Dec 2005 11:36 GMT
> Right now, if I get an object of a generalized class, for example
> Message, I have to do an instanceof to cast the object to a more
[quoted text clipped - 13 lines]
>
> myriam

If you use a type field in the Message class you can forego the if
statements in favor of a switch statement.

public void receiveMessage(Message m)
{
  switch(m.getType())
  {
     case m.STOP_TYPE:
        parseMessage((StopMessage)m);
        break;
  }
}

If appropriate, you could also consider a change in design to use
polymorphism instead.  You would then implement the class that parses the
messages as a listener, and register it on the Message.

public void receiveMessage(Message m)
{
  m.setListener(this);
  m.parse();
}

class Message
{
  public abstract void parse();
}

class StopMessage
{
  public void parse()
  {
     listener.parseMessage(this);
  }
}

Neither of these solutions seems all that much cleaner or better than
your original though.

Signature

Beware the False Authority Syndrome

Roedy Green - 10 Dec 2005 22:27 GMT
>  case m.STOP_TYPE:
>         parseMessage((StopMessage)m);
>         break;

I run in to this pattern all the time.  I don't know how you can avoid
at least one switch statement that looks up the message number and
selects the appropriate parser for that message type.

You might disguise it a bit with a HashMap that looks up the message
number/string and gives you a .class object from which you can do a
new Instance of the parser/message object.  You still need code to
register all the parsers, which gets you back to code much like the
switch.

I have avoided using classForName, though that might work too.
Doing that destroys the beauty of GenJar finding all your dependent
classes for you.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Patrick May - 11 Dec 2005 15:01 GMT
> >  case m.STOP_TYPE:
> >         parseMessage((StopMessage)m);
[quoted text clipped - 3 lines]
> avoid at least one switch statement that looks up the message number
> and selects the appropriate parser for that message type.

    There are a number of ways to decouple the message routing logic
from the message parsing logic.  One is to use a Chain of
Responsibility:

         http://www.spe.com/pjm/message-broker.html

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc.    | The experts in large scale distributed OO
                        | systems design and implementation.
         pjm@spe.com    | (C++, Java, Common Lisp, Jini, CORBA, UML)
Roedy Green - 11 Dec 2005 20:31 GMT
>          http://www.spe.com/pjm/message-broker.html

You are right back where you started, just with the code you were
trying to hide slightly deeper under the rug. You still need code to
register all the methods. This in effect amounts to composing the
switch statement on the fly.  You still need a place that knows all
the messages.

What you want is for a message class to be self-registering.  It can't
register itself unless somebody at least knows to call some dummy
static method.

You could do it easily if you could say "get me a list of all classes
on the classpath that implement interface X, and load them and run
their static initialisers.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Patrick May - 11 Dec 2005 21:20 GMT
> >          http://www.spe.com/pjm/message-broker.html
>
[quoted text clipped - 3 lines]
> switch statement on the fly.  You still need a place that knows all
> the messages.

    No, you don't.  The implementation provided allows new message
types to be loaded by explicit demand, but one of the suggested
alternatives is to load any new subtypes on the classpath dynamically.

    The important issue is that no changes need to be made to
existing, tested, working code in order to add a new message type (or,
with suitable design, to change an existing message type
implementation).  This is in stark contrast to the use of a switch
statement.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc.    | The experts in large scale distributed OO
                        | systems design and implementation.
         pjm@spe.com    | (C++, Java, Common Lisp, Jini, CORBA, UML)
Roedy Green - 11 Dec 2005 21:52 GMT
>     The important issue is that no changes need to be made to
>existing, tested, working code in order to add a new message type (or,
>with suitable design, to change an existing message type
>implementation).  This is in stark contrast to the use of a switch
>statement.

Then how does a message type get registered if there is not some
central list or central code that does the registering?

Adding a entry to a switch is in principle little different from
adding a line to a list of method calls or a line to properties file,
which granted has the small advantage of not recompiling any existing
code.
.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Patrick May - 11 Dec 2005 22:18 GMT
> >     The important issue is that no changes need to be made to
> > existing, tested, working code in order to add a new message type
[quoted text clipped - 4 lines]
> Then how does a message type get registered if there is not some
> central list or central code that does the registering?

    As described, the new message type can either be loaded by
explicitly specifying it to the message broker, by registering a proxy
with the message broker, by having the message broker look for new
message types in the classpath as necessary, or through any of a
number of other designs.

> Adding a entry to a switch is in principle little different from
> adding a line to a list of method calls or a line to properties
> file, which granted has the small advantage of not recompiling any
> existing code.

    That's far more than a recompilation issue.  Changing existing,
tested, working code is a significant risk.  In many organizations, it
requires significant testing parallel execution time.  The capability
of adding new message types dynamically has measurable value.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc.    | The experts in large scale distributed OO
                        | systems design and implementation.
         pjm@spe.com    | (C++, Java, Common Lisp, Jini, CORBA, UML)
Chris Uppal - 10 Dec 2005 13:44 GMT
> Right now, if I get an object of a generalized class, for example
> Message, I have to do an instanceof to cast the object to a more
> specialized class and then call the specialized method with an
> appropriate cast.

Another way to avoid type-tests is to use double-dispatch.  That can be quite
elegant where it is appropriate, but can also be used to "cover-up" bad design
(using the technical paraphinalia of OO programming to hide what is basically a
non-OO design).

   -- chris
J. Verdrengh - 11 Dec 2005 13:38 GMT
In Java (and many other OO programming languages) there is the principle of
dynamic binding.

1    Parent instance = new Child();
2    instance.method1();

Assuming Child extends Parent & Child overrides method1(), in line 2
Child.method1() is invoced. This kind of dynamic binding is related to
overriden methods.

I've always wondered why there isn't something like dynamic binding based on
the (runtime) type of an argument, so dynamic binding related to overloaded
methods:

class Test{
   public void method1(Parent parent){...}
   public void method1(Child child){...}
}

1    Test test = new Test();
2    Parent instance = new Child();
3    test.method1(instance);

Why Java doesn't apply dynamic binding in this case? In line 3, the
invocation is statically (at compile time) bound to the Test.method1(Parent
parent), but I don't see which problems may arise when dynamic binding is
applied (so at runtime the decision is made to invoce Test.method1(Child
child) ).

All clarifying insights are greatly appreciated :-)

Jeroen
J. Verdrengh - 11 Dec 2005 14:38 GMT
> but I don't see which problems may arise when dynamic binding is applied

After some thinking I've realized that overloaded methods with multiple
parameters will result in non-trivial (runtime) decisions concerning which
method will be chosen. Probably this would introduce too much complexity for
the designers of the application?

e.g.:

class Test{
   public void method1(Parent parent, Child child){...}
   public void method1(Child child, Parent parent){...}
}

1    Test test = new Test();
2    Parent instance1 = new Child();
3    Parent instance2 = new Child();
4    test.method1(instance1, instance2);
Chris Uppal - 12 Dec 2005 10:05 GMT
> After some thinking I've realized that overloaded methods with multiple
> parameters will result in non-trivial (runtime) decisions concerning which
> method will be chosen. Probably this would introduce too much complexity
> for the designers of the application?

I don't think the particular issue you raised (which I trimmed) is so very much
more serious than the equivalent problem with static resolution of overloaded
methods.  Several OO languages do work with dynamic dispatch based on the types
of all the arguments (e.g. Lisp+CLOS and, iirc, Eiffel, perhaps Sather too ?)
and it is definitely a valid option in the language design space.

My guess is that Java doesn't work that way because the designers wanted to
stick to conservative, well-proven, language features.  And -- for once -- I
think they got it right[*].  Multi-methods are also quite tricky to implement
efficiently, especially in a context like Java where code is loaded
dynamically.

   -- chris

([*] IMO multimethods are a complicating distraction from sound OO
programming.)
Roedy Green - 11 Dec 2005 20:32 GMT
>I've always wondered why there isn't something like dynamic binding based on
>the (runtime) type of an argument, so dynamic binding related to overloaded
>methods:

see http://mindprod.com/jgloss/nice.html

It binds based on run time types.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.



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.