It seems that Java can't choose the most appropriate method implementation based on the runtime type of an argument, as documented here. Recapitulating the example:
class Superclass {}
class Subclass extends Superclass {}
class Test {
p开发者_C百科ublic void aMethod(Superclass s) {...}
public void aMethod(Subclass s) {...}
}
Which method of the Test class is executed is determined based on the type of the reference, not the type of the instance. Again, based on the linked examples:
Test aTest = new Test();
Superclass aSuper = new Subclass();
test.aMethod(aSuper);
It is aMethod(Superclass s)
that executes, not aMethod(Subclass s)
.
I was trying to create a variation on the listener pattern, where listeners 'plug in' via an interface, and the listeners have methods defined for subclasses of the interfaces.
As a quick example of what I mean, say I'm building an alarm clock that can have functionality plugged in.
The implementation for the above I had in mind would look like an interface Event
, with a subclass WakeUpEvent
, and an interface EventListener
requiring implementation of handle(Event evt)
.
I hoped to create a class implementing a no-op handle(Event evt)
with a specific handle(WakeUpEvent evt)
if the listener wanted to deal with that type of event.
Of course, this approach won't work as-is - the obvious solution is runtime instanceof
checks - yuk.
Are there any patterns or approaches that I can use to get the behaviour I want?
Visitor pattern is what you need
These situations are when I think of Visitor or double dispatch pattern.
As others have pointed out, you could use a Visitor pattern.
However, I would encourage you to think about an alternative approach as this all seems like a design smell to me.
Shouldn't aMethod actually be defined in SuperClass rather than Test? Then you can override aMethod in the SubClass, and the correct version will be called at runtime.
This is not a direct answer but more a hint to understand the problem.
What you describe is a confusing mix of method overloading (used in the Test
class) from overriding (used to describe what you want to achieve by implementing EventListener
but then overloading handle
).
The reason for this behaviour is that overloading results in a compile-time decision which method will be invoked. Thus, if you use overloading it is a good idea to have mutually incompatible argument types to avoid such confusion.
精彩评论