默认实现还是抽象方法?

Sco*_*ott 24 java polymorphism default abstract-methods

将方法的默认实现放在超类中更好,并在子类想要偏离它时重写它,或者你应该只留下超类方法摘要,并在许多子类中重复正常实现?

例如,我参与的项目有一个类,用于指定它应该停止的条件.抽象类如下:

public abstract class HaltingCondition{
    public abstract boolean isFinished(State s);
}
Run Code Online (Sandbox Code Playgroud)

一个简单的实现可能是:

public class AlwaysHaltingCondition extends HaltingCondition{
    public boolean isFinished(State s){
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们用对象做这个的原因是我们可以随意组合这些对象.例如:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我们有一些暂停条件需要通知事件已经发生.例如:

public class HaltAfterAnyEventHaltingCondition extends HaltingCondition{
    private boolean eventHasOccurred = false;

    public void eventHasOccurred(Event e){
        eventHasOccurred = true;
    }

    public boolean isFinished(State s){
        return eventHasOccurred;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们应该如何最好地代表eventHasOccurred(Event e)抽象超类?大多数子类可以具有此方法的无操作实现(例如AlwaysHaltingCondition),而一些子类需要重要的实现才能正确操作(例如HaltAfterAnyEventHaltingCondition),而其他子类不需要对消息执行任何操作,但必须将其传递给其下属,以便他们将正确运作(例如ConjunctionHaltingCondition).

我们可以有一个默认实现,它可以减少代码重复,但会导致一些子类编译但如果没有被覆盖则不能正常运行,或者我们可以将方法声明为abstract,这将需要每个子类的作者考虑一下它们提供的实现,尽管十分之九会是无操作实现.这些策略的其他优缺点是什么?一个比另一个好多少?

Jon*_*eet 15

一种选择是有另一个抽象类,作为超类的所有实现使用希望使用默认的实现.

就个人而言,我通常将抽象类中的非最终方法抽象(或者仅使用接口),但它肯定取决于具体情况.例如,如果你有一个包含许多方法的接口,并且你希望能够选择加入其中的一些方法,那么一个抽象类就可以为每个方法以无操作的方式实现接口.

基本上,你需要根据其优点来评估每个案例.