3

私は次のメソッドを持つインターフェース(と呼ばれるSubject)を持っています:

public void addObserver(Observer o);

Subject次に、と呼ばれる拡張する別のインターフェイスがありますTimerSubject。このインターフェイスは、のより具体的なバージョンでありSubject、タイミングに使用されます。他にもいくつかの方法があります。

対応する2つのインターフェイス、、、もありObserverますTimerObserverTimerObserver拡張しObserverます。

クラスがを実装するとき、インターフェースからメソッドTimerSubjectをオーバーライドする必要があります。これは次のようになります。addObserver()Subject

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

TimerObserver問題は、の代わりに受け入れるメソッドが必要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にオブザーバーを拡張させることで、addObserverメソッドを使用するユーザーがオブザーバーの追加にのみ使用されることを保証できます。これはボーナスです。このようにして、多形ゲッターを書くこともできます。

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)の実装があるSubjectを拡張します。その実装が完全に機能しなくなった場合は、オーバーライドしてエラーをスローできます。しかし、TimerSubjectが実際にaddObserver(Observer)メソッドを使用せず、そのメソッドが完全に機能していない場合、おそらくこれら2つのオブジェクトは希望するほど多形ではありません。:)

于 2012-04-05T06:30:01.433 に答える