将一个方法的默认实现放在父类(super class)中,并在子类想要偏离它时重写它更好,还是应该保留父类(super class)方法抽象,并在许多子类中重复正常实现?
例如,我参与的一个项目有一个类,用于指定应该停止的条件。抽象类如下:
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;
}
}
我们应该如何在抽象父类(super class)中最好地表示 eventHasOccurred(Event e)
?大多数子类可以有此方法的无操作实现(例如 AlwaysHaltingCondition
),而有些需要重要的实现才能正确操作(例如 HaltAfterAnyEventHaltingCondition
),而另一些则不需要对消息做任何事情,但必须将其传递给他们的下属,以便他们能够正确操作(例如 ConjunctionHaltingCondition
)。
我们可以有一个默认实现,这将减少代码重复,但如果不覆盖它会导致一些子类编译但不能正确运行,或者我们可以将方法声明为抽象,这需要作者每个子类都要考虑他们提供的实现,尽管十分之九是无操作实现。这些策略的其他优点和缺点是什么?一个比另一个好很多吗?
最佳答案
一种选择是拥有另一个抽象子类,用作所有确实想要使用默认实现的实现的父类(super class)。
我个人通常将非 final方法抽象留在抽象类中(或者只使用接口(interface)代替),但这绝对取决于具体情况。例如,如果您有一个包含许多方法的接口(interface),并且您希望能够选择加入其中的一些,那么可以使用一个抽象类以无操作方式为每个方法实现接口(interface)方法很好。
基本上,您需要评估每个案例的优点。
关于java - 默认实现还是抽象方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3595731/