メソッドのデフォルトの実装をスーパークラスに配置し、サブクラスがこれから逸脱したい場合にそれをオーバーライドする方がよいでしょうか?それとも、スーパークラスのメソッドを抽象化したままにして、多くのサブクラスで通常の実装を繰り返すべきでしょうか?
たとえば、私が関与しているプロジェクトには、停止する条件を指定するために使用されるクラスがあります。抽象クラスは次のとおりです。
public abstract class HaltingCondition{
public abstract boolean isFinished(State s);
}
些細な実装は次のようになります。
public class AlwaysHaltingCondition extends HaltingCondition{
public boolean isFinished(State s){
return true;
}
}
オブジェクトでこれを行う理由は、これらのオブジェクトを任意に一緒に構成できるからです。例えば:
public class ConjunctionHaltingCondition extends HaltingCondition{
private Set<HaltingCondition> conditions;
public void isFinished(State s){
boolean finished = true;
Iterator<HaltingCondition> it = conditions.iterator();
while(it.hasNext()){
finished = finished && it.next().isFinished(s);
}
return finished;
}
}
ただし、イベントが発生したことを通知する必要がある停止条件がいくつかあります。例えば:
public class HaltAfterAnyEventHaltingCondition extends HaltingCondition{
private boolean eventHasOccurred = false;
public void eventHasOccurred(Event e){
eventHasOccurred = true;
}
public boolean isFinished(State s){
return eventHasOccurred;
}
}
eventHasOccurred(Event e)
抽象スーパークラスでどのように表現するのが最適でしょうか? ほとんどのサブクラスは、このメソッドの no-op 実装を持つことができます (例: AlwaysHaltingCondition
)。一部のサブクラスは、正しく動作するために重要な実装を必要とし (例HaltAfterAnyEventHaltingCondition
:それらは正しく動作します (例: ConjunctionHaltingCondition
)。
コードの重複を減らすデフォルトの実装を持つことができますが、一部のサブクラスがコンパイルされても、オーバーライドされていない場合は正しく動作しません。または、メソッドを抽象として宣言することもできます。彼らが提供していた実装について考えてみてください。これらの戦略のその他の長所と短所は何ですか? 一方は他方よりもはるかに優れていますか?