简体   繁体   English

我可以判断是否调用了抽象方法吗?

[英]Can I tell if an abstract method has been called?

Given this class: 给定此类:

abstract class Foo{
    public Foo(){...}

    public abstract void checkable();

    public void calledWhenCheckableIsCalled(){
        System.out.println("checkable was called");
    }
}

Is there any code I can put in Foo's constructor to make calledWhenCheckableIsCalled get called when checkable is called? 是否有任何代码,我可以把Foo的构造,使calledWhenCheckableIsCalled被调用时, checkable被称为?

Note: This is a gross simplification of an actual project I am working on. 注意:这是我正在从事的实际项目的简化。

Edit: I have already implemented a template pattern workaround. 编辑:我已经实现了模板模式的解决方法。 I just wondered if there was another way to do this I am missing. 我只是想知道是否还有另一种方式可以做到这一点,我很想念。 (Perhaps using reflection.) (也许使用反射。)

Looks like a template method pattern . 看起来像模板方法模式

But then you must implement Foo.checkable() and introduce another abstract method to delegate to. 但是,您必须实现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");
    }
}

I would also suggest to make checkable() final in this case so that you can be sure that checkable() can not implemented in another way as you expected. 我还建议在这种情况下使checkable()最终化,以便可以确保checkable()不能以您期望的其他方式实现。

In addition to Brian Roach's comment 除了Brian Roach的评论

The downside is that the protected can be expanded to public in the subclass, so you can't explicitly enforce it. 缺点是受保护的对象可以在子类中扩展为public,因此您不能明确地强制执行它。

That's true, but you can prevent a Foo instance from being instantiated if a subclass increases the visibility of doCheckable . 是的,但是如果子类增加了doCheckable的可见性,则可以防止实例化Foo实例。 Therefore you have to introduce a verification whenever an object is instantiated. 因此,无论何时实例化对象,您都必须引入验证。 I would recommend to use an initializer code so that the verification is executed on every constructor that exists. 我建议使用初始化程序代码,以便对存在的每个构造函数执行验证。 Then it can not be forgotten to invoke and therefore be by-passed. 这样就不能忘记调用它,因此可以忽略它。

For example: 例如:

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();
        }
    }
}

Since the check is implemented using reflection the downside is that it is only checked at runtime. 由于检查是使用反射实现的,所以缺点是只能在运行时进行检查。 So you will not have compiler support of course. 因此,您当然不会获得编译器支持。 But this approach let you enforce that an instance of a Foo can only exist if it fulfills your contract. 但是,通过这种方法,您可以强制执行Foo的实例只有在履行合同时才能存在。

No, the constructor will get invoked once during the object initialisation. 不,构造函数将在对象初始化期间被调用一次。 You can however get your subclass that provides the implementation to call the method in the super class: 但是,您可以获取提供用于调用超类中的方法的实现的子类:

class Bar extends Foo {

    // implementation of abstract method
    public void checkable(){
        super.calledWhenCheckableIsCalled(); // call to parent's method
        ...
    }
}

EDIT 编辑

You could achieve this with aspects. 您可以通过方面来实现这一目标。 Using an aspect you can intercept each call to a method by referring to the abstract parent method. 使用方面,您可以通过引用抽象父方法来拦截对方法的每次调用。 This leaves you free from interfering eith the child code. 这样您就可以不受子代码的干扰。 Your calledWhenCheckableIsCalled code would then become part of the intercepting code. 然后,您的calledWhenCheckableIsCalled代码将成为拦截代码的一部分。

abstract class Foo {

    // use pointcut to intercept here
    public void checkable();
}

There is no way as you are forcing that method to implement in child . 您无法强迫该方法在child实现。

An awkward suggestion will be know from child implementation. 从孩子的实现中可以看出一个尴尬的建议。 I mean there is no clean way AFAIK 我的意思是没有干净的方法AFAIK

abstract class foo {

    public abstract void bar();

    public void moo() {
        System.out.println("some code");

        this.bar();

        System.out.println("more code");
    }
}

now if moo is called, the underlying implementation of bar will be used, it is just a small paradigm shift from what you want. 现在,如果调用moo ,将使用bar的基础实现,这只是您想要的很小的范式转换。

so your end user would call moo instead of bar , but he still needs to implement bar 因此您的最终用户将呼叫moo而不是bar ,但是他仍然需要实现bar

Nope, an abstract method doesn't have a body. 不,抽象方法没有主体。 You could, however, chain your method like this: 但是,您可以像这样链接您的方法:

abstract class Foo {

    void callMeInstead() {

        // do common

        callMeImplementation();
    }

    abstract void callMeImplementation();
}

It looks to me like you're looking for the template pattern: 在我看来,您正在寻找模板模式:

public abstract class Template {
    public final void checkable() {
        calledWhenCheckableIsCalled();
        doCheckable();
    }

    protected abstract void doCheckable();

    private  void calledWhenCheckableIsCalled() {
        System.out.println("checkable was called");
    }
}

Now, each time checkable() is called, calledWhenCheckableIsCalled() is also called. 现在,每次checkable()被调用, calledWhenCheckableIsCalled()也被称为。 And the suclass must still provide the actual implementation of checkable() , by implementing the doCheckable() method. 而suclass仍必须提供实际执行的checkable()通过实现doCheckable()方法。

Note that making checkable() final prevents a subclass from overriding it and thus bypassing the call to calledWhenCheckableIsCalled() . 请注意,将checkable() final可以防止子类重写它,从而绕过对calledWhenCheckableIsCalled()的调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM