代码之家  ›  专栏  ›  技术社区  ›  m_vitaly

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

  •  7
  • m_vitaly  · 技术社区  · 16 年前

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

    现在问题部分: 例如,在运行时,我希望能够检查 this 类不为空,如果为空,则应将其更改为字符串“空”。

    我可以使用反射来遍历变量并得到它们的值。但是如果我扩展我的类并添加私有的甚至是受保护的变量,我的基类就不能访问它们。我必须 setAccessible 在我可以使用变量之前。

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

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

    是因为我不能还是不应该这样限制我的子类?


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

    4 回复  |  直到 7 年前
        1
  •  7
  •   JP Alioto    16 年前

    这很简单,因为它违反了封装。另一个类不应该接触到您的类中,并且在处理一些事情,即使您概括了该类。例如,一辆车如何知道关于一辆车的任何事情?基本类的全部要点是提供子类,但是就像一个过度保护的父类一样,您的建议太多了。

        2
  •  7
  •   Yishai    16 年前

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

    因为类知道它自己的实现——它定义了它,所以在限制对其他实例的访问方面没有任何收获,因为类实现声明了所有私有实例,它已经公开了所有这些细节。

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

        3
  •  4
  •   Scott Stanchfield    16 年前

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

    Java的可见性规则说明

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

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

        4
  •  0
  •   Grant Wagner    16 年前

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

    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 . 什么时候? 测试1 是写的, 测试2 可能根本不存在。

    而且,基类(超级类)不知道它是从什么时候继承的。为了让基类知道它何时被继承,您必须能够在从它继承时修改基类。你是说我应该修改我的本地副本吗? ArrayList 当我写:

    class MyArrayList extends ArrayList
    

    当我决定在你的计算机上运行我的代码的那一天发生了什么,你收到我修改过的 数组列表 那就知道了 MyArrayList 还是我要以某种方式修改您计算机上的副本?

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