views:

118

answers:

6

Hi,

I'm trying to dispatch objects to separate method according to their subclass.

For instance, consider those 2 objects

class A extends I {}
class B extends I {}

and the method

void dispatch(I i) {}

in dispatch(), I'd like to invoke a method according to the type of i. Hence if i is actually of type A, the handlerA(A a) method will be called. If it's of type B, handlerB(B b) will be called, and so on ... I tried with method overloading but I guess it doesn't work this way

what is the best way to achieve this ? I'd like to avoid using if/else statement ...

Thanks in advance,

edit: I can't modify any of those classes.

+3  A: 

So in I you declare the handler() method, and implement it appropriately (i.e. differently) in both A and B.

This is Polymorphism :)

Noon Silk
This assumes that `handler()` makes sense to have on `A` and `B`. If that's the case, your answer is 100% correct.
Kevin Montrose
Kevin: You're right, it does. But only kind of. I still think the OP is missing the underlying concept of Polymorphism, and even if my exact suggestion isn't suitable, I think some scheme of a function/property in `I` is the way to go.
Noon Silk
if handler() is in I, and both A and B implement I, but it doesn't make sense to have handler() on both, I think there are **probably** other problems.
Carl
sorry I should have specified that I can't change any of thoses classes.
pinpinlelapin
pinpinlelapin: Yes ... that changes things. If you can't change A or B or I, you'll need to do type-checking. Which is really quite, well, not ideal, to say the least.
Noon Silk
+1  A: 

Use the Visitor Pattern.

In short, have I declare an accept(Visitor<T> ...) method, and have Visitor expose onA(A ...), onB(B ...), etc. methods. Your implementations of the I interface will call the appropriate method on the passed in Visitor<T>.

Its probably not worth it (due to boilerplate) if you only have 2 concrete classes, but somewhere around 3 or 4 it starts being worth it - if just to avoid duplicated if-else constructs.

Kevin Montrose
+1  A: 

Since your edit, I assume you cannot edit A,B and I; this leads to bad news:

You can inherit from A say C in this class (C) you may call super.dispatch() so you can reach the base class A.dispatch().

  • But due to design (unconsidered inheritance) you cannot reach I. This would be like calling super.super which is not allowed

  • In Java, you can't call super().super().. Childs have acces to their parents, but not to their grandparents.

So you're a victim of bad design. EDIT: fixed typo

stacker
A: 

Looks like the only way you can do this is to use type checking. I understand that this is not supposed to be encouraged, but...

void dispatch(I i)
{
   if(i instanceof A)
   {
      handlerA();
   } 
   else 
   {
      handlerB();
   }
}

But seriously, if you can avoid it at all, do not write code like this. If you can't modify them, could you by any chance extend A and B, add in a different handler() method for both and and use these new subclasses instead of A and B?

Jimmeh
A: 

I think that the Adapter Pattern is more applicable than the Visitor Pattern in this case.

Stephen C
how exactly? (15)
Bozho
A: 

If you could use Scala, you can write

i match {
  case a: A => handlerA(a) 
  case b: B => handlerB(b)
  case _ => throw new Exception("Unknown i: " + i.toString)
}
eed3si9n