Java方法扩展而不是覆盖

时间:2013-04-15 18:14:03

标签: java inheritance annotations

Java中是否有某种类型的@annotation或其他方法来强制执行方法扩展而不是覆盖?

具体来说,假设我有一个Foo类:

class Foo {
    public void bar(Thing thing) {
        // ...
    }
}

有没有一种方法可以在编译时强制执行任何扩展Foo的类X,并覆盖bar,首先调用super.bar(thing)

5 个答案:

答案 0 :(得分:3)

不,你必须明确地写它。

构造函数的旁注:在实例化子类时将隐式调用超类'nullary构造函数,但后者的构造函数有很多参数。

答案 1 :(得分:1)

通常,您可以做的是创建一个调用可扩展方法的final方法。

class Foo {

    @Override
    public final void bar(Thing thing) {
        // super code comes here
        this.doBar(thing);
    }

    public abstract void doBar(Thing thing);

}

致电时

foo.bar(thing);

首先运行超级代码,然后运行子类中的代码。

这样您就可以保护完整的bar逻辑,并且只允许扩展/重新实现某些部分。

此外,它允许您后处理结果,或者将代码分解到某些子任务。

答案 2 :(得分:1)

您可以将bar声明为final,然后从bar调用抽象方法,这会强制子类实现“扩展”。

abstract class Foo {
    public final void bar(Thing thing) {
        barImpl(thing);
        overrideMe(thing);
    }

    private final void barImpl(Thing thing) {
        // Original implementation of "bar" here.
    }

    protected abstract void overrideMe(Thing thing);
}

修改

我已将overrideMepublic更改为protected,因此Foo的用户不能只调用overrideMe而不是bar

答案 3 :(得分:0)

虽然你不能强制代码在编译时调用它的超类,但是在运行时检测代码不会调用超类时并不难。

class Foo {
    private boolean baseCalled;
    public final void bar(Thing thing) {
        baseCalled = false;
        barImp(thing);
        if (!baseCalled) {
            throw new RuntimeException("super.barImp() not called");
        }
    }
    protected void barImp(Thing thing) {
         baseCalled = true;
         . . . // base class implementation of bar
    }
}

请注意,这可以扩展到多个继承级别,而无需进一步详细说明。该方法特别适用于从Foo内调用的方法;在这些情况下,您通常可以放弃final限定符并重定向到实现方法,只需定义基类方法来设置标志。清除标志将在每个调用点完成。

以上模式在Android框架中广泛使用。它不保证super.barImp在子类覆盖中被称为第一件事;只是它被称为。

答案 4 :(得分:0)

如果您使用的是EJB,则可以尝试使用@AroundInvoke注释。

通过使用反射,您可以在类中找到相同的方法,并且您可以使用与调用原始方法相同的参数调用它。

请注意,在这种情况下,您必须避免super.bar(thing)次调用,否则会被调用两次。