4

I have following abstract class:

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

A sub class extends the abstract class:

public class MyAction extends AbstractCreateActionHandler {

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

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

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

Question:

Is it possible that a developer which extends the abstract class and implements executeAction() method is not allowed the change the visibilty of executeAction()?

At the moment a developer can simply change the visibilty of the method to "public", create an object of the subclass and invoke executeExtion(). The visibility modifier can be changed and the abstract method is still accepted as "implemented".

So the "normal" calling sequence and checks which are executed in abstract class method invoke() can be bypassed. Is there a way to check if the invoke() method was called?

sk2212
  • 1,688
  • 4
  • 23
  • 43

3 Answers3

4

Is it possible that a developer which extends the abstract class and implements executeAction() method is not allowed the change the visibilty of executeAction()?

No, this is not possible.

Chapter 8.4.8.3. Requirements in Overriding and Hiding of the Java Language Specification specifies:

The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows: ...

So it is always possible to have the overriding method provide more access than the overridden method in the parent class.

See also java access modifiers and overriding methods.

Community
  • 1
  • 1
Andreas Fester
  • 36,091
  • 7
  • 95
  • 123
4

No, there's not really a way to restrict that. are you worried about malicious developers or clueless coworkers? if the latter then you just need to establish coding conventions like "don't increase the visibility of methods" and put some javadoc on the abstract method indicating proper usage. if the former, then you probably need to design your code differently (possibly using the strategy pattern).

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • 1
    Okay...I might have known it. So there is also no way to check if invoke() method was called, right? The strategy pattern looks good. Will have a closer look. – sk2212 Mar 28 '13 at 13:53
  • @sk2212 - well, there are heinous ways to do it like getting the current stack trace and looking back through it, or maintaining a member var like "inInvoke", but i wouldn't recommend any of those :) – jtahlborn Mar 28 '13 at 14:20
0

It is allowed to change the modifier to public because it does not violate the Liskov Substitution Principle.

So the "normal" calling sequence and checks which are executed in abstract class method invoke() can be bypassed. Is there a way to check if the invoke() method was called?

If you pass someone the reference to AbstractCreateActionHandler then the caller will not be able to see the method executeAction as it is not public in AbstractCreateActionHandler class. So the caller will not be able to bypass execution sequence if you pass reference to Base class to caller. If you pass reference to Concrete class then the sequence can be broken.

Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120