How to invoke a java method based on a subclass type?
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 ov开发者_StackOverflow中文版erloading 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.
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.
So in I
you declare the handler()
method, and implement it appropriately (i.e. differently) in both A
and B
.
This is Polymorphism :)
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 allowedIn 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
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?
I think that the Adapter Pattern is more applicable than the Visitor Pattern in this case.
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)
}
精彩评论