4

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

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

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

有没有一种方法可以在编译时强制任何扩展 Foo 并且还覆盖 bar 的类 X 调用super.bar(thing)first?

4

5 回答 5

3

不,你必须明确地写出来。

构造函数的旁注:实例化子类时将隐式调用超类的空构造函数,无论后者的构造函数有多少参数。

于 2013-04-15T18:15:14.253 回答
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逻辑,并且只允许扩展/重新实现某些部分。

此外,它还允许您对结果进行后处理,或将代码分解为某些子任务。

于 2013-04-15T18:20:59.830 回答
1

您可以声明barfinal,然后从 调用抽象方法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);
}

编辑

我已从 更改overrideMepublicprotected因此用户Foo不能只调用overrideMe而不是bar.

于 2013-04-15T18:22:54.653 回答
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被称为第一件事;只是它被称为。

于 2013-04-15T18:43:30.400 回答
0

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

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

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

于 2013-04-15T19:11:34.783 回答