简体   繁体   中英

Java class whose fields are only accessible to its subclasses (without getters/setters)?

What I really want is a class with a generic constructor, and when a subclass' identical constructor is invoked, the subclass will have access to the same fields. Here is an example of what I would like to do:

public abstract class Command{
    private Mediator m

    public Command(Mediator med){
       m = med;
    }

    abstract void exec();
}

public class FoobarCommand extends Command{
    public FoobarCommand(Mediator med){
        super(med);
    }

    public void exec(){
        med.doAFoobar()
    }
 }

public static void main(String[] args){
    Mediator m = new Mediator();
    Command c = new FoobarCommand(m);
    c.exec();
}

Obviously this won't work because FoobarCommand doesn't have direct access to Mediator med. So how would you access the med field? I don't want anyone else but the subclasses to have access to it, and "protected" is not an option because I want people to be able to create their own commands (which obviously would be outside the package).

There is actually no such access modifier, strictly speaking. It's impossible to declare a field (or method/class, for that matter) only accessible to subclasses; the most restrictive modifier you can use is protected , which still allows access to other classes in the parent class' package.

But other than that niggle, protected is the way to go.

Edit : to clarify that protected is an option. To access a protected method, you must be either a subclass or within the same package; you don't have to be both. So a subclass of Command created in a different package would still be able to access (super).m .

声明Mediator Med为“受保护”而非私人。

you need to declare Mediator m protected in your mother class.

Moreover, in the exec() method in your subclass , you need to do m.doAFoobar() instead of med.doAFoobar() since med is not a member but a formal parameter of your constructor.

abstract class Command {
    protected Mediator m

    public Command(Mediator med){
        m = med;
    }

    abstract void exec();
}

The class is not public, so it can only be extended by other classes in the same package and 'm' is protected so it can be accessed by derived classes.

If you give med protected access it will be available to subclasses outside of the package.

http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

If you want a field to be accessible to only the class itself and any derived classes and other classes in that package, use the protected keyword. That's what it's there for, and it should still work even outside the package. Instead of having them call med.doFoobar();, they need to call m.doFoobar();

Alternately, you could create a protected (or public, even) get function. That way you expose the ability to get the mediator, but you don't have to let them overwrite it after it's declared.

However, what you want (unable to be read inside the package) is impossible in java keywording. But, since you're the one writing this particular package, couldn't you just not access it from inside the package? Or create your own package with just this file? There's no way to allow subclasses access and not allow classes in the package.

What you can do is give the subclass a variable that is named the exact same thing, then set it equal to the superclass using constructors and methods like

public abstract class Command{
    private Mediator m

    public Command(Mediator med){
       m = med;
    }

    abstract void exec();
}

public class FoobarCommand extends Command{

    private Mediator m;

    public FoobarCommand(Mediator med){
        super(med);
        m = med;
    }

    public void exec(){
        m.doAFoobar()
    }
 }

public static void main(String[] args){
    Mediator m = new Mediator();
    Command c = new FoobarCommand(m);
    c.exec();
}

However, this is limited in what it can do. As m is an object reference, changes to m in the subclass will be reflected in the superclass; however, this would not occur if the class member was a primitive. (Given all primitives have an object equivalent, this can be worked around if slightly clunky)

The subclass must also directly receive the reference, as that's where a copy to the reference is stored. For abstract superclasses this is fine as you are guaranteed a subclass, but below that you have to be careful how you handle the data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM