保持子类中抽象方法的可见性

时间:2013-03-28 13:33:34

标签: java abstract-class visibility

我有以下抽象类:

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()的可见性?

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

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

3 个答案:

答案 0 :(得分:4)

  

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

不,这是不可能的。

Java语言规范的第8.4.8.3. Requirements in Overriding and Hiding条指定:

  

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

因此,总是可以让覆盖方法提供更多访问权限,而不是父类中重写的方法。

另见java access modifiers and overriding methods

答案 1 :(得分:4)

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

答案 2 :(得分:0)

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

  

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

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