默认实现还是抽象方法?
是将方法的默认实现放在超类中,并在子类想要偏离此值时重写它,还是应该将超类方法抽象出来,并在许多子类中重复正常实现?
例如,我参与的一个项目有一个类,用于指定它应停止的条件。抽象类如下所示:
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;
}
}
我们应该如何在抽象超类中最好地表示?大多数子类可以具有此方法的no-op实现(例如),而有些子类需要重要的实现才能正常运行(例如),而其他子类不需要对消息执行任何操作,但必须将其传递给其下属,以便它们能够正确操作(例如)。eventHasOccurred(Event e)
AlwaysHaltingCondition
HaltAfterAnyEventHaltingCondition
ConjunctionHaltingCondition
我们可以有一个默认的实现,这将减少代码重复,但如果它没有被覆盖,会导致一些子类编译但无法正常运行,或者我们可以将方法声明为抽象,这将要求每个子类的作者考虑他们提供的实现,尽管十次中有九次它是no-op实现。这些策略的其他优缺点是什么?一个比另一个好得多吗?