Java 我能知道是否调用了抽象方法吗?
鉴于这一类别:Java 我能知道是否调用了抽象方法吗?,java,design-patterns,reflection,abstract-methods,Java,Design Patterns,Reflection,Abstract Methods,鉴于这一类别: abstract class Foo{ public Foo(){...} public abstract void checkable(); public void calledWhenCheckableIsCalled(){ System.out.println("checkable was called"); } } 我是否可以在Foo的构造函数中放入任何代码,以便在调用checkable时调用calledWhenChe
abstract class Foo{
public Foo(){...}
public abstract void checkable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
我是否可以在Foo的构造函数中放入任何代码,以便在调用checkable时调用calledWhenCheckableIsCalled
注:这是一个我正在工作的实际项目的粗略简化
编辑:我已经实现了一个模板模式解决方案。我只是想知道是否还有其他方法可以做到这一点,我错过了。可能是使用反射。没有办法,因为您正在强制在child中实现该方法
一个尴尬的建议将从儿童实施中得知。我的意思是没有干净的方法,因为您正在强制在child中实现该方法
一个尴尬的建议将从儿童实施中得知。我的意思是没有干净的方法,因为aik不,构造函数将在对象初始化期间被调用一次。但是,您可以让提供实现的子类调用超类中的方法:
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();
}
否,构造函数将在对象初始化期间被调用一次。但是,您可以让提供实现的子类调用超类中的方法:
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();
}
现在,如果调用moo,将使用bar的底层实现,这只是您想要的一个小小的范式转换
所以您的最终用户将调用moo而不是bar,但他仍然需要实现bar
现在,如果调用moo,将使用bar的底层实现,这只是您想要的一个小小的范式转换
因此,您的最终用户将调用moo而不是bar,但他仍然需要实现bar不,抽象方法没有主体。但是,您可以像这样链接您的方法:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}
不,抽象方法没有主体。但是,您可以像这样链接您的方法:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}
看起来像是一辆汽车
但是,您必须实现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设置为final,这样您就可以确保checkable不能以您期望的其他方式实现
除了Brian Roach的评论之外
缺点是,protected可以在子类中扩展为public,因此不能显式地强制执行它
的确如此,但是如果子类增加了doCheckable的可见性,则可以防止Foo实例被实例化。因此,无论何时实例化对象,都必须引入验证。我建议使用初始值设定项代码,以便在存在的每个构造函数上执行验证。那么它就不能忘记调用,因此就被忽略了
例如:
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的实例只有在它满足你的合同时才能存在
但是,您必须实现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设置为final,这样您就可以确保checkable不能以您期望的其他方式实现
除了Brian Roach的评论之外
缺点是,protected可以在子类中扩展为public,因此不能显式地强制执行它
的确如此,但是如果子类增加了doCheckable的可见性,则可以防止Foo实例被实例化。因此,无论何时实例化对象,都必须引入验证。我建议使用初始值设定项代码,以便在存在的每个构造函数上执行验证。那么它就不能忘记调用,因此就被忽略了
例如:
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的实例只有在它满足您的合同时才能存在。在我看来,您正在寻找模板模式:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
现在,每次调用checkable时,都会调用whencheckableiscalled。而suclass仍然必须通过实现doCheckable方法来提供checkable的实际实现
请注意,使chec
kable final可防止子类重写它,从而绕过调用calledWhenCheckableIsCalled的调用。在我看来,您正在寻找模板模式:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
现在,每次调用checkable时,都会调用whencheckableiscalled。而suclass仍然必须通过实现doCheckable方法来提供checkable的实际实现
请注意,将checkable设置为final可以防止子类重写它,从而绕过调用CalledWhenCheckable的调用。@BrianRoach Sigh,我很确定这不会起作用。这将使我想要的功能更容易实现。调用checkable的唯一方法是在其中放入一些代码。或者围绕它创建包装器方法。我想不出一种方法可以像你所要求的那样做到这一点,但你可以检查它是否在使用各种模拟框架(即Mockito或JMockit)的单元测试期间被调用。我的意思是,你可以使它受到保护,并通过抽象类中的公共代理方法调用它。。。但这就是我所能得到的。我已经实现了一个变通方法,但这将使我的代码更加优雅。@BrianRoach叹了口气,我很确定这不会奏效。这将使我想要的功能更容易实现。调用checkable的唯一方法是在其中放入一些代码。或者围绕它创建包装器方法。我想不出一种方法可以像你所要求的那样做到这一点,但你可以检查它是否在使用各种模拟框架(即Mockito或JMockit)的单元测试期间被调用。我的意思是,你可以使它受到保护,并通过抽象类中的公共代理方法调用它。。。但这就是我的全部。我已经实现了一个变通方法,但这将使我的代码更加优雅。我知道这将如何工作,但我真的不想切换到使用AspectJ。我知道这将如何工作,但我真的不想切换到使用AspectJ。+1-这是我在评论中得到的。缺点是在子类中受保护的可以扩展为public,因此您不能显式地强制执行它。@BrianRoach是的,您是对的。我只看到一种方法,通过在构造函数中使用反射检查来防止子类增加可见性。我更新了我的答案。你觉得怎么样?嘿,这当然是一种强制执行的方式:如果可以的话,我会再次投票给你。@BrianRoach是的。我的意思是编译器不能执行它。也许不清楚。我考虑过并更新了+这就是我在评论中的意思。缺点是在子类中受保护的可以扩展为public,因此您不能显式地强制执行它。@BrianRoach是的,您是对的。我只看到一种方法,通过在构造函数中使用反射检查来防止子类增加可见性。我更新了我的答案。你觉得怎么样?嘿,这当然是一种强制执行的方式:如果可以的话,我会再次投票给你。@BrianRoach是的。我的意思是编译器不能执行它。也许不清楚。我考虑过并更新了