确保方法执行,即使被覆盖也是如此

时间:2013-12-06 22:19:17

标签: java class oop hierarchy

假设我有一些方法的接口,如下所示:

interface Task {
    void before();
    void doStuff();
    void after();
}

在这里,我将实现其中的一部分:

abstract class PoliteTask implements Task{

    @Override
    public void before() {
        System.out.println("Hey");
    }


    @Override
    public abstract void doStuff();


    @Override
    public void after() {
        System.out.println("Cya");
    }

}

现在我想确保在所有扩展类中调用那些before()after()实现。

这里我们有一个需要在before()中初始化的类:

class ActualStuffTask extends PoliteTask {

    private int fancyNumber;


    @Override
    public void before() {
        // init some things
        fancyNumber = 42;
    }


    @Override
    public void doStuff() {
        System.out.println("Look, a number: "+fancyNumber);
    }

}

显然,ActualStuffTask会覆盖before(),因此它不会说“嘿”,只会说“Cya”。

如果我在PoliteTask final中创建方法,这不会发生,但是它的子类无法覆盖方法。

super.before()中调用ActualStuffTask会有效,但无论子类实现如何,我都希望保证这种效果。

问题是:

我应该使用什么模式来同时实现父实现和子实现?

4 个答案:

答案 0 :(得分:5)

我喜欢使用您在实现类中实现的抽象方法。

abstract class PoliteTask implements Task{

    @Override
    public final void before() {
        System.out.println("Hey");
        doBefore();
    }

    protected abstract void doBefore();
    protected abstract void doAfter();

    @Override
    public abstract void doStuff();


    @Override
    public final void after() {
        System.out.println("Cya");
        doAfter();
    }

}

class ActualStuffTask extends PoliteTask {
    private int fancyNumber;

    @Override
    protected void doBefore() {
        // init some things
        fancyNumber = 42;
    }


    @Override
    public void doStuff() {
        System.out.println("Look, a number: "+fancyNumber);
    }


    @Override
    protected void doAfter() {
        // something else
    }
}

请注意,Task方法是final。他们不需要。这取决于您构建API的方式。

答案 1 :(得分:3)

这种情况的常用方法是这样的(简化示例):

abstract class Base {

    public final void before() {
        System.out.println("Hey");
        doBefore();
    }

    protected void doBefore() {
    }
}

这样基本代码总是会被执行,子类可以添加它们的实现。

答案 2 :(得分:1)

您可以关注template method pattern。在final(例如AbstractClass)中创建一个doAll方法,按顺序调用其他方法:

public final void doAll() {
    before();
    doStuff();
    after();
}

然后,您可以使beforeafter成为final方法,这样它们将始终由子类执行,并且无法更改其行为。

答案 3 :(得分:1)

一种选择是明确调用super.before()课程中的ActualStuffTask

@Override
public void before() {
    super.before();
    // init some things
    fancyNumber = 42;
}

另一种选择是更改父类的设计,并使用before关键字“保护”final方法:

abstract class PoliteTask implements Task {

    @Override
    public final void before() {
        System.out.println("Hey");
        internalBefore();
    }

    protected abstract void internalBefore(); // child class should override this method

    ...

}