3

我有一个Subject具有以下方法的接口(称为):

public void addObserver(Observer o);

然后我有另一个扩展Subject名为TimerSubject. 这个接口是一个更具体的版本Subject,用于计时。它还有一些其他的杂项方法。

还有两个对应的接口Observer, 和TimerObserverTimerObserver延伸Observer

当一个类实现TimerSubject时,它必须重写接口中的addObserver()方法Subject。看起来像这样:

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

问题是,我需要接受 aTimerObserver而不是 的方法Observer,它看起来像这样:

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

这不起作用,因为参数与被覆盖的方法的参数不同。

那么有没有办法用多态的参数覆盖一个方法呢?

4

2 回答 2

2

我不得不做一次这样的事情,我最终做的是模板化它,即

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 接口的每个具体实现者添加不同类型的观察者。所以你让主题界面要求它。通过让泛型类 T 扩展 Observer,您仍然可以保证使用 addObserver 方法的人仅用于添加 Observer,这是一个好处。这样您也可以编写多态吸气剂,例如

public T getObserver(T e);

填写任何派生类的类型。这边走

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

还将静态类型检查。(注意:我在这里工作记忆,所以最后一点可能不完全正确,但肯定有一些方法可以得到它。)

于 2013-07-11T19:38:42.727 回答
1

想到了几个解决方案:

如果您的 TimerSubject 实现接收到不是 TimerObserver 的参数,则可以通过抛出 RuntimeException 来实现 public void addObserver (Observer)。您失去了编译器对您强制类型的保护,但后期绑定对于“真正的”多态性来说是相当典型的。

或者,您的 TimerSubject 接口可以简单地为新行为指定一个新方法 addTimerObserver。大概您的 TimerSubject 扩展了一个已经实现 addObserver(Observer); 的主题。如果该实现完全失效,您可以覆盖并抛出错误。但是如果 TimerSubject 真的没有使用 addObserver(Observer) 方法并且该方法完全失效,那么这两个对象可能不像您想要的那样多态。:)

于 2012-04-05T06:30:01.433 回答