0

I have an abstract class called MyAction which contains a protected enum variable. The class is defined as follows:

package mypackage;

public abstract class MyAction {
    public enum ActionId {
        ACTION1, ACTION2;
    }

    protected ActionId actionId;

    // constructor
    public MyAction(ActionId actionId) {
        this.actionId = actionId;
    }

    public ActionId getActionId() {
        return actionId;
    }    
    ...
    ...
}

I created a specific action, MyAction1, that extends MyAction:

package mypackage;

public class MyAction1 extends MyAction {
    public MyAction1() {
        super(ActionId.ACTION1);
    }
    ...
    ...
}    

I have a singleton utility class (in the same package) that creates an instance of MyAction1 and stores it in a HashMap:

package mypackage;

public class MyActionFactory {
    private static MyActionFactory theInstance;
    private HashMap<ActionId, MyAction> actions;

    private MyActionFactory() {
        actions = new HashMap<ActionId, MyAction>();
        MyAction1 myAction1 = new MyAction1();
        actions.put(myAction1.actionId, myAction1); // able to access protected variable actionId
    }

    public static VsActionFactory getInstance() {
        if (theInstance == null)
            theInstance = new VsActionFactory();
        return theInstance;
    }    
    ...
    ...
}

Note that in the method actions.put(myAction1.actionId, myAction1) I am able to access the protected member actionId.

Why is it that I can access the protected member actionId (contained in the base class MyAction) of the instance of MyAction1? I thought protected members were only accessible to subclasses.

Does it have anything to do with MyActionFactory being in the same package as the others?

rene
  • 41,474
  • 78
  • 114
  • 152
Jan Tacci
  • 3,131
  • 16
  • 63
  • 83

2 Answers2

1

The protected keyword makes things visible within the same package. Which is the case, because both of your classes are in package mypackage.

Here is a nice table, taken from Oracle.com:

enter image description here

Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • Now I know that. I guess I could have tested it by moving the utility class to another package. – Jan Tacci Sep 01 '13 at 16:20
  • So there is no way of making a variable in the base class that's only accessible to subclasses and not to other classes in the same package? – Jan Tacci Sep 01 '13 at 16:21
  • No that is not possible. – Martijn Courteaux Sep 01 '13 at 16:22
  • I noticed something strange looking at your table. If you don't define a modifier then other classes can access it but not sub-classes (even if the sub-class is defined in the same package)? – Jan Tacci Sep 01 '13 at 16:25
  • The best way to sum it up is to see that each higher level of access fully encompasses lower levels: it's a strict hierarchy of expanding circles. – Marko Topolnik Sep 01 '13 at 16:25
  • Good way to look at it! – Jan Tacci Sep 01 '13 at 16:25
  • @MarkoTopolnik: Indeed. However, to me it feels like the level of package and subclass should be swapped around. What do you think? – Martijn Courteaux Sep 01 '13 at 16:26
  • 1
    You mean, swap the Package and Subclas *columns*, so that we get a modifier which allows *only* the subclasses in? The way it is works better for me: a package is a set of closely coupled classes, they are all "friends" in C++ terms. `protected`, on the other hand, is a form of public access, to be used in classes designed for public extension. It would make little sense to allow public extension, but preclude package-private access. – Marko Topolnik Sep 01 '13 at 16:31
  • Oh, you are right! I was mixing up the concept inner class with subclass. When I saw the table and I was thinking of subclass as of a, innerclass, I was disappointed. Thanks for pointing that out. – Martijn Courteaux Sep 01 '13 at 17:30
0

Protected access modifier allows access in the same package + sub classes in other packages.You can remember it as default access plus inheritance.

Malwaregeek
  • 2,274
  • 3
  • 15
  • 18