在Java中,为什么超类方法不能从子类实例访问受保护的或私有的方法/变量?

时间:2009-05-22 18:51:29

标签: java oop class inheritance instance

让我们从另一个行为开始:即使您将方法/变量声明为私有,同一个类的另一个实例也可以访问它。没关系,我可以忍受它。我将这些类称为私有而非实例私有。

现在问题部分: 例如,在运行时,我希望能够检查this类中的所有String变量是否为空,如果它们为null,则应将其更改为字符串“NULL”。

我可以使用反射来运行变量并获取它们的值。但是如果我扩展我的类并添加私有甚至受保护的变量,我的基类就无法访问它们。在使用变量之前,我必须先对setAccessible进行变换。

所以请向我解释为什么基类(超类)不能从其子类访问私有/受保护变量。它是它的子类,所以我不明白。这背后的想法是什么?

我知道超类不应该知道它的子类,但在我的例子中它是有意义的,不是吗?

是不是因为我不能或不应该以这种方式限制我的子类?


更新 根据答案,我还想知道:为什么不从同一个类中访问另一个实例的私有变量被视为违反封装?

4 个答案:

答案 0 :(得分:7)

这很简单,因为它违反了封装。另一堂课不应该进入你的班级,并且要乱搞一些事情,即使你把这个课程概括。例如,车辆如何了解汽车的任何信息?基类的重点是提供子类,但是像过度保护的父类一样,你建议的内容太多了。

答案 1 :(得分:7)

要回答您的更新问题(因为原始问题已得到很好的回答),私有的目的是隐藏实现细节,以便这些实现细节不会成为依赖关系。这是面向对象编程的本质 - 封装确保通过将不同部分隔离到自己的区域来保持复杂性。

由于类知道它自己的实现 - 它定义了它,因此限制对其他实例的访问没有任何好处,因为类实现声明它已经暴露给所有这些细节的所有私有实例。

在这种情况下隐藏它实际上会增加复杂性,因为您必须添加额外的访问级别以允许类级别可见性而不是实例级别可见性,而不实际封装任何进一步的复杂性。

答案 2 :(得分:4)

这都是关于继承和封装的。

Java的可见性规则说明了

  1. 私人成员只能在定义它们的类中访问
  2. 受保护的成员只能访问
    • 定义它们的类
    • 定义它们的类的子类
    • 与定义它们的类相同的包中的其他类
  3. 当然,正如您所提到的,在反思中您可以更改规则(除非SecurityManager禁止它)

答案 3 :(得分:0)

我倾向于从务实和现实的角度来看待它:

public class Test1 {
    private int a = 1;

    public static void main(String s[]) {
        System.out.println((new Test1()).a);
        System.out.println((new Test1()).getA());
        System.out.println((new Test2()).getA());
    }

    public int getA() { return a; }
}

class Test2 extends Test {
    private int a = 2;

    public int getA() { return a; }
}

您建议Test1使用哪种语法来访问a中的私人成员Test2。撰写Test1时,Test2可能甚至不存在。

同样,基类(超类)不知道它何时被继承。要允许基类知道何时继承它,您必须能够在继承基类时修改它。你建议我在写作时以某种方式修改ArrayList的本地副本:

class MyArrayList extends ArrayList

当我决定在您的计算机上运行我的代码时,会发生什么事情,您是否获得了ArrayList的{​​{1}}的修改后的副本,或者我是否会以某种方式修改您计算机上的副本?

这些问题可以以某种方式克服吗?当然。允许它有什么价值吗?没有我能看到的。