Search code examples
javaclassinheritancesuperclass

Java class inheritance and blocking superclass methods


Im currently making a simple pluginable program. My problem is that I don't want to let plugin access all base-plugin fields/methods. For example:

public abstract class BasePlugin {
    private int x; //Mysterious x
    public abstract void update(); //update func that may need x, but can't change it
    protected final int getX() {return x;} //x accessor
}

And that would work unless you realize that there is no way to set x.

What can I do? I want to make subclass (plugin) unable to change x, but let it read the value. Value should be accesible at least once when creating (that would be enough).

EDIT: Constructor works in most cases, but what if I have for example:

public abstract class BasePlugin {
    private List<int> x; //Mysterious x
    public abstract void update(); //update func that may need x, but can't change it
    protected final List<int> getX() {return x;} //x accessor
    public BasePlugin(List<int> y) {x = y;}
}

public class Plugin {
    public Plugin(List<int> y)
    {
        super(y);
        y.remove(0); //Will it work?
    }
}

Solution

  • An abstract class is permitted to have a constructor, so you can create a parameterless constructor for BasePlugin:

    public abstract class BasePlugin {
        private int x; //Mysterious x
        public BasePlugin() {
            x = 42;
        }
        public abstract void update(); //update func that may need x, but can't change it
        protected final int getX() {return x;} //x accessor
    }
    

    And now when a plugin is created, x is set to 42. You don't even need to make any code changes to the plugins to make them use this constructor.


    To answer the edited question: If x is a List and you don't want the plugins to modify it, your constructor should be copying it and wrapping it in an unmodifiable list. Otherwise, any plugin can call getX().add(myObject).

    public BasePlugin(List<int> y) {
        List<int> temp = new ArrayList<int>();
        Collections.copy(temp, y); // shallow copy of the list
        this.x = Collections.unmodifiableList(temp);
    }
    

    Now if the plugin's constructor is

    public Plugin(List<int> y)
    {
        super(y);
        y.remove(0); //Will it work?
    }
    

    It will have no effect on the BasePlugin's list.