7

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

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

我可以使用反射来遍历变量并获取它们的值。但是,如果我扩展我的类并添加私有甚至受保护的变量,我的基类将无法访问它们。我必须先setAccessible了解变量,然后才能使用它们。

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

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

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


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

4

4 回答 4

7

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

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

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

于 2009-05-22T22:30:45.417 回答
7

它就像违反封装一样简单。即使您概括了该班级,另一个班级也不应该能够进入您的班级并弄乱事物。例如,车辆如何知道有关汽车的任何信息?基类的全部意义在于提供子类,但就像过度保护的父母一样,你的建议太多了。

于 2009-05-22T18:59:11.040 回答
4

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

Java 的可见性规则指出

  1. 私有成员只能在定义它们的类中访问
  2. 受保护的成员只能在
    • 定义它们的类
    • 定义它们的类的子类
    • 与定义它们的类在同一包中的其他类

当然,正如您所提到的,在反思中您可以更改规则(除非 SecurityManager 禁止它)

于 2009-05-22T19:02:24.060 回答
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访问. 当被写入时,可能甚至不存在。aTest2Test1Test2

同样,基类(超类)也不知道它是从什么时候继承而来的。为了让基类知道它何时被继承,您必须能够在从它继承时修改基类。您是否建议我ArrayList在编写时以某种方式修改我的本地副本:

class MyArrayList extends ArrayList

当我决定在你的计算机上运行我的代码的那一天会发生什么,你会得到我修改过的ArrayList那个知道的副本MyArrayList,还是我会以某种方式修改你计算机上的副本?

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

于 2009-05-22T19:26:13.857 回答