【问题标题】:Keep visibility of abstract method in subclass保持子类中抽象方法的可见性
【发布时间】:2013-03-28 13:33:33
【问题描述】:

我有以下抽象类:

public abstract class AbstractCreateActionHandler {

    protected IWorkItem mCurrentWI;

    public AbstractCreateActionHandler(IWorkItem wi) {
      this.mCurrentWI = wi; 
    }

    public final void invoke() {
      try {
          if (checkForLockingFile()) {
            this.executeAction();
            Configuration.deleteInstance();
          }
      } catch (IOException e) {
          Configuration.deleteInstance();
          e.printStackTrace();
      }
    }

    protected abstract void executeAction();    

    private boolean checkForLockingFile() throws IOException {
      String path = Configuration.getInstance().getProperty("path");
      File lock = new File(path + "lock_"+mCurrentWI.getId()+"__.tmp");
      if(!lock.exists()) {
          lock.createNewFile();
          return true;
      }
      return false; 
    }
}

子类扩展抽象类:

public class MyAction extends AbstractCreateActionHandler {

    public MyAction(IWorkItem wi) {
      super(wi);
    }

    @Override
    protected void executeAction() {
      // Implementation
    }

    // ALSO POSSIBLE...
    /* @Override
    public void executeAction() {
      // Implementation
    }*/
}

问题:

是否允许扩展抽象类并实现executeAction()方法的开发人员不允许更改executeAction()的可见性?

目前,开发人员可以简单地将方法的可见性更改为“公共”,创建子类的对象并调用executeExtion()。可见性修饰符可以更改,抽象方法仍然被接受为“已实现”。

因此可以绕过抽象类方法invoke()中执行的“正常”调用序列和检查。有没有办法检查invoke()方法是否被调用?

【问题讨论】:

    标签: java abstract-class visibility


    【解决方案1】:

    不,没有真正的方法来限制它。您是否担心恶意开发人员或无知的同事?如果是后者,那么您只需要建立编码约定,例如“不要增加方法的可见性”,并将一些 javadoc 放在抽象方法上,指示正确使用。如果是前者,那么您可能需要以不同的方式设计代码(可能使用策略模式)。

    【讨论】:

    • 好吧...我可能已经知道了。所以也没有办法检查是否调用了 invoke() 方法,对吧?策略模式看起来不错。会仔细看看。
    • @sk2212 - 好吧,有一些令人发指的方法可以做到这一点,比如获取当前堆栈跟踪并回顾它,或者维护一个像“inInvoke”这样的成员变量,但我不推荐任何那些:)
    【解决方案2】:

    是否允许扩展抽象类并实现executeAction()方法的开发人员不允许更改executeAction()的可见性?

    不,这是不可能的。

    Java 语言规范的8.4.8.3. Requirements in Overriding and Hiding 章规定:

    覆盖或隐藏方法的访问修饰符(第 6.6 节)必须提供至少与覆盖或隐藏方法一样多的访问权限,如下所示:...

    因此,与父类中的被覆盖方法相比,覆盖方法总是可以提供更多访问权限。

    另见java access modifiers and overriding methods

    【讨论】:

      【解决方案3】:

      允许将修饰符更改为public,因为它不违反Liskov Substitution Principle

      所以“正常”的调用顺序和执行的检查 抽象类方法 invoke() 可以被绕过。有没有办法 检查是否调用了 invoke() 方法?

      如果您将AbstractCreateActionHandler 的引用传递给某人,那么调用者将无法看到executeAction 方法,因为它在AbstractCreateActionHandler 类中不公开。因此,如果您将对基类的引用传递给调用者,调用者将无法绕过执行序列。如果你传递对 Concrete 类的引用,那么序列可能会被破坏。

      【讨论】:

        猜你喜欢
        • 2015-02-09
        • 1970-01-01
        • 1970-01-01
        • 2013-09-12
        • 2017-12-29
        • 2010-12-13
        • 1970-01-01
        • 1970-01-01
        • 2015-08-02
        相关资源
        最近更新 更多