overloading methods

M

mabramso

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
 
O

Oliver Wong

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.

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
 
A

Alex Molochnikov

Oliver Wong said:
<code>
public void receiveMessage(Message m) {
if (m instanceof StopMessage)
receiveMessage((StopMessage) m);
}
}
</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
 
O

Oliver Wong

Alex Molochnikov said:
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.

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".
Did you mean:

mh.receiveMessage(this);

in this and other method?

Yes, sorry.

- Oliver
 
P

Patrick May

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);
}

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
 
A

Abhijat Vatsyayan

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
 
Z

zero

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

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.
 
C

Chris Uppal

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
 
R

Roedy Green

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.
 
J

J. Verdrengh

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

J. Verdrengh

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);
 
P

Patrick May

Roedy Green said:
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.

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
 
R

Roedy Green


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.
 
P

Patrick May

Roedy Green said:
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.

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
 
R

Roedy Green

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.
..
 
P

Patrick May

Roedy Green said:
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
 
C

Chris Uppal

J. Verdrengh said:
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.)
 
M

mabramso

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!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top