鉴于此课程:
abstract class Foo{
public Foo(){...}
public abstract void checkable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
我可以在Foo的构造函数中添加任何代码,以便在调用calledWhenCheckableIsCalled
时调用checkable
吗?
注意:这是我正在进行的实际项目的大致简化。
编辑:我已经实现了模板模式解决方法。我只是想知道是否还有另一种方法可以做到这一点我很想念。 (也许使用反射。)
答案 0 :(得分:4)
但是你必须实现Foo.checkable()
并引入另一个抽象方法来委托。
abstract class Foo{
public Foo(){}
public void checkable(){
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
我还建议在这种情况下使checkable()
成为最终版本,这样您就可以确保checkable()
无法以您预期的其他方式实现。
除了Brian Roach的评论
缺点是受保护的内容可以在子类中扩展为public,因此您无法明确强制执行。
这是事实,但是如果子类增加Foo
的可见性,则可以阻止实例化doCheckable
实例。因此,只要实例化对象,就必须引入验证。我建议使用初始化代码,以便在存在的每个构造函数上执行验证。然后它不能忘记调用,因此被旁路。
例如:
abstract class Foo {
{ // instance initializer code ensures that enforceDoCheckableVisibility
// is invoked for every constructor
enforceDoCheckableVisibility();
}
public Foo() {...}
public Foo(Object o) {...}
private void enforceDoCheckableVisibility() {
Class<?> currentClass = getClass();
while (currentClass != Foo.class) {
try {
Method doCheckableMethod = currentClass.getDeclaredMethod("doCheckable");
if (Modifier.isPublic(doCheckableMethod.getModifiers())) {
throw new RuntimeException("Visibility of "
+ currentClass.getSimpleName()
+ ".doCheckable() must not be public");
}
} catch (SecurityException | NoSuchMethodException e) {}
currentClass = currentClass.getSuperclass();
}
}
}
由于使用反射实现检查,因此缺点是仅在运行时检查。所以你当然不会有编译器支持。但是这种方法允许您强制Foo
的实例只有在履行合同时才能存在。
答案 1 :(得分:2)
不,在对象初始化期间,构造函数将被调用一次。但是,您可以获得提供实现的子类来调用超类中的方法:
class Bar extends Foo {
// implementation of abstract method
public void checkable(){
super.calledWhenCheckableIsCalled(); // call to parent's method
...
}
}
修改强>
你可以用方面实现这一点。使用方面,您可以通过引用抽象父方法来拦截对方法的每个调用。这样您就不会干扰子代码。您的calledWhenCheckableIsCalled
代码将成为拦截代码的一部分。
abstract class Foo {
// use pointcut to intercept here
public void checkable();
}
答案 2 :(得分:0)
您无法在child
中强制实施该方法。
从儿童实施中可以了解到一个尴尬的建议。我的意思是没有干净的方式 AFAIK
答案 3 :(得分:0)
abstract class foo {
public abstract void bar();
public void moo() {
System.out.println("some code");
this.bar();
System.out.println("more code");
}
}
现在如果调用moo
,将使用bar
的基础实现,这只是你想要的一个小范式转换。
因此,您的最终用户会拨打moo
而不是bar
,但他仍需要实施bar
答案 4 :(得分:0)
不,抽象方法没有正文。但是,你可以像这样链接你的方法:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}
答案 5 :(得分:0)
在我看来,你正在寻找模板模式:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
现在,每次调用checkable()
时,也会调用calledWhenCheckableIsCalled()
。而且,通过实施checkable()
方法,蔗糖仍然必须提供doCheckable()
的实际实施。
请注意,使checkable()
为final会阻止子类覆盖它,从而绕过对calledWhenCheckableIsCalled()
的调用。