Java类,其字段只能由其子类访问(没有getter / setter)?

时间:2009-10-01 16:28:23

标签: java

我真正想要的是一个带有泛型构造函数的类,当调用子类'相同的构造函数时,子类将可以访问相同的字段。以下是我想要做的一个例子:

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

显然这不起作用,因为FoobarCommand无法直接访问Mediator med。那么你将如何访问med领域?我不希望除了子类之外的任何人都可以访问它,并且“protected”不是一个选项,因为我希望人们能够创建自己的命令(显然它们不在包中)。

7 个答案:

答案 0 :(得分:13)

严格来说,实际上没有这样的访问修饰符。声明一个字段(或方法/类,对于这个问题)只能可以访问子类;您可以使用的限制性最强的修饰符是protected,它仍允许访问父类包中的其他类。

但除此之外,protected是可行的方法。

编辑:澄清受保护的选项。要访问受保护的方法,您必须 在同一个包中的子类;你不必两个都是。因此,在不同的包中创建的Command的子类仍然可以访问(super).m

答案 1 :(得分:5)

宣布Mediator Med为“受保护”而非私人。

答案 2 :(得分:2)

你需要宣告Mediator在你的母班中受到保护。

此外,在子类的exec()方法中,您需要执行m.doAFoobar()而不是med.doAFoobar(),因为med不是成员,而是构造函数的形式参数。

答案 3 :(得分:1)

abstract class Command {
    protected Mediator m

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

    abstract void exec();
}

该类不是公共的,因此它只能由同一个包中的其他类扩展,并且'm'受到保护,因此可以通过派生类访问它。

答案 4 :(得分:1)

如果您提供med受保护的访问权限,它将可用于包外的子类。

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

答案 5 :(得分:1)

如果希望只有类本身以及该包中的任何派生类和其他类可以访问字段,请使用protected关键字。这就是它的用途,它甚至应该在包装之外工作。他们不需要调用med.doFoobar();而是需要调用m.doFoobar();

或者,您可以创建受保护(或公共,偶数)的get函数。这样你就暴露了获取中介的能力,但你不必让它们在声明后覆盖它。

然而,在java keywording中,你想要的东西(无法在包内读取)是不可能的。但是,既然你是编写这个特定软件包的人,那么你不能从包内部访问它吗?或者只用这个文件创建自己的包?没有办法允许子类访问,也不允许包中的类。

答案 6 :(得分:0)

你可以做的是给子类一个名为完全相同的变量,然后使用构造函数和方法将它设置为超类,如

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

但是,它的功能有限。由于m是一个对象引用,对子类中m的更改将反映在超类中;但是,如果类成员是基元,则不会发生这种情况。 (鉴于所有基元都具有等效的对象,如果稍微笨重,这可以解决)

子类还必须直接接收引用,因为存储了引用的副本。对于抽象超类,这很好,因为你可以保证一个子类,但在下面你必须小心处理数据。