Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我能知道是否调用了抽象方法吗?_Java_Design Patterns_Reflection_Abstract Methods - Fatal编程技术网

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是的。我的意思是编译器不能执行它。也许不清楚。我考虑过并更新了