views:

193

answers:

2

I have this simple interface/class:

public abstract class Message {

}

public class Message1 extends Message{

}

public class Message2 extends Message{

}

And an utility class:

 public class Utility {       
public void handler(Message m){
    System.out.println("Interface: Message");  }

 public void handler(Message1 m){
    System.out.println("Class: Message1"); }

 public void handler(Message2 m){
    System.out.println("Class: Message2"); } 

}

Now, the main class:

public static void main(String[] args) {

        Utility p=new Utility();

        Message1 m1=new Message1();
        p.handler(m1);

        Message m=(Message) m1;
        p.handler(m);

}

The output is

Class: Message1 Interface: Message

I would that p.handler(m) call the method p.handler(m:Message1)

I don't want use the "manual" command instanceof because I have many cases:

if(m instance of Message1)
p.handler((Message1)m)
else if (m instanceof Message2)
p.handler((Message2)m)

...

If I call m.getClass() I obtain "mypackage.Message1", so the subclass and not the superclass.

I try with this code (use reflection):

p.handler(m.getClass().cast(m));

But the output is Interface: Message

So, this is my problem. I would do a runtime cast of superclass object to subclassobject without use the "code command" istanceof.

I would a right command like this:

p.handler((m.getclass)m);

How can I obtain it? It's possible?

Thank in advance.

Fabrizio

+4  A: 

Java will call the method on the basis of information known at compile time. What you could do is add a method to the interface that calls the correct handler method for the object.

public abstract class Message {

    public void callHandler(Utility utility);

}

public class Message1 extends Message{

    public void callHandler(Utility utility) {
        utility.handler(this);
    }
}

Your calls to the handler become:

Message m=(Message) m1;
m.callHandler(p);

which now calls Utility::handler(Message1) even though the reference in main is of type of the Message interface.

rsp
@rsp: add the 'abstract' keyword to the callHandler method in Message.
Eyal Schneider
simple, right and without reflection! Thank
jfabrizio
+1 "what is known at compile time" is the key
leonbloy
A: 

I am not sure what your handle(..) methods are supposed to do, but since they depend on the specific instance of Message, you should consider adding handle() method to your Message class (as abstract method). This way, each message implements its version of handle, and you can enjoy the benefits of polymorphism:

Message m = new Message1();
m.handle();

This code will return "Class: Message1", as you need.

Eyal Schneider