2012-04-05 2 views
3

У меня есть интерфейс (так называемый Subject), который имеет следующий метод:Переопределение метод с полиморфными аргументами

public void addObserver(Observer o); 

Я тогда другой интерфейс, который расширяет Subject называется TimerSubject. Этот интерфейс является более конкретной версией Subject, используемой для синхронизации. В нем есть несколько других разных методов.

Существует также два соответствующих интерфейса: Observer и TimerObserver. TimerObserver extends Observer.

Когда класс реализует TimerSubject, он должен переопределить метод addObserver() с интерфейса Subject. Это выглядит следующим образом:

@Override 
public void addObserver(**Observer e**) { 
    observers.add(e); 
} 

Проблема заключается в том, мне нужен способ, чтобы принять TimerObserver вместо Observer, ведьма будет выглядеть следующим образом:

@Override 
public void addObserver(**TimerObserver e**) { 
    observers.add(e); 
} 

Это не работает, так как аргументы не совпадают с аргументами переопределенного метода.

Так есть способ переопределить метод с аргументами, которые являются полиморфными?

+0

Вы можете использовать дженерики –

ответ

1

Несколько решений приходят на ум:

Ваша реализация TimerSubject может осуществлять публичный недействительный addObserver (Observer), бросая RuntimeException, если он принимает аргумент, который не является TimerObserver. Вы теряете защиту от типа компилятора, но поздняя привязка довольно типична для «истинного» полиморфизма.

В качестве альтернативы интерфейс TimerSubject может просто указать новый метод addTimerObserver для нового поведения. Предположительно, ваш TimerSubject расширяет тему, которая уже имеет реализацию addObserver (Observer); если эта реализация будет полностью прекращена, вы можете переопределить и выбросить ошибку. Но если TimerSubject действительно не используется для метода addObserver (Observer), и этот метод полностью не функционирует, то, возможно, эти два объекта не так полиморфны, как вам бы хотелось. :)

2

я должен был сделать что-то подобное когда-то, что я в конечном итоге делает его было templatizing, т.е.

interface Subject<T extends Observer> { 
public void addObserver(T e); 
} 

class TimerSubject implements Subject<TimerObserver> { 
// ... 
@Override 
public void addObserver(TimerObserver e) 
{ 
    observers.add(e); 
} 
} 

Это держит метод addObserver полиморфная и навязывает тип аргумента статически.

Идея заключается в том, что если вы хотите, чтобы каждый конкретный конструктор интерфейса Subject добавлял разные виды наблюдателей. Поэтому вы задаете интерфейс Subject. Благодаря тому, что общий класс T расширяет Observer, вы все же можете гарантировать, что люди, использующие метод addObserver, используются только для добавления в Observers, что является бонусом. Таким образом, вы можете написать полиморфный геттер, что-то вроде

public T getObserver(T e); 

заполнение типов для любых производных классов. Таким образом

Subject<?> foo = new TimerSubject(); 
// add observer somewhere 
Observer bar = foo.getObserver(); 

также будет статически проверять тип.(Примечание: я работаю с памятью здесь, так что последний бит может быть не совсем правильным, но определенно есть способ получить его таким образом.)

Смежные вопросы