Overriding a method with polymorphic arguments
I have an interface (called Subject
) that has the following method:
public void addObserver(Observer o);
Then I have another interface that extends Subject
called TimerSubject
. This interface is the more specific version Subject
used for synchronization. It has several other different methods.
There are also two corresponding interfaces: Observer
and TimerObserver
. TimerObserver
extends Observer
.
When the class implements TimerSubject
, it must override the method addObserver()
from the interface Subject
. It looks like this:
@Override
public void addObserver(**Observer e**) {
observers.add(e);
}
The problem is I need a method to accept TimerObserver
instead Observer
, whitch would look like this:
@Override
public void addObserver(**TimerObserver e**) {
observers.add(e);
}
This does not work because the arguments are not the same as the arguments of the overridden method.
So, is there a way to override a method with arguments that are polymorphic?
source to share
Several solutions come to mind:
A TimerSubject implementation can implement public void addObserver (Observer), throwing out a RuntimeException if it receives an argument that is not a TimerObserver. You lose compiler type protection, but late binding is fairly typical of "true" polymorphism.
Alternatively, your TimerSubject interface can simply specify a new addTimerObserver method for the new behavior. Presumably your TimerSubject is extending a theme that already has an addObserver (Observer) implementation; if this implementation is completely abandoned, you can override and throw an error. But if TimerSubject isn't really used for the addObserver (Observer) method, and that method doesn't fully function, then maybe these two objects aren't as polymorphic as you'd like. :)
source to share
I had to do something like this once, what I ended up doing was templating it, i.e.
interface Subject<T extends Observer> {
public void addObserver(T e);
}
class TimerSubject implements Subject<TimerObserver> {
// ...
@Override
public void addObserver(TimerObserver e)
{
observers.add(e);
}
}
This prevents the addObserver method from polymorphism and applies the argument type statically.
The idea here is that if you want each specific Subject interface designer to add different kinds of observers. Therefore, you specify the Subject interface. Because the generic class T extends Observer, you can still ensure that people using the addObserver method are only used to add to Observers, which is a bonus. This way you can write a polymorphic getter, something like
public T getObserver(T e);
filling of types for any derived classes. Thus
Subject<?> foo = new TimerSubject();
// add observer somewhere
Observer bar = foo.getObserver();
will also statically check the type. (Note: I'm working with memory here, so the last bit might not be entirely correct, but definitely somehow get it that way.)
source to share