Java中是否有某种类型的@annotation或其他方法来强制执行方法扩展而不是覆盖?
具体来说,假设我有一个Foo类:
class Foo {
public void bar(Thing thing) {
// ...
}
}
有没有一种方法可以在编译时强制执行任何扩展Foo的类X,并覆盖bar,首先调用super.bar(thing)
?
答案 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);
}
修改强>
我已将overrideMe
从public
更改为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)
次调用,否则会被调用两次。