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?

+3


source to share


2 answers


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. :)

+1


source


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.)

+2


source







All Articles