【问题标题】:Do Subclasses Inherit Private Instance Variables From Superclasses子类是否从超类继承私有实例变量
【发布时间】:2012-05-16 11:41:58
【问题描述】:

Do subclasses inherit private fields?

这个问题解决了同样的问题,但我不太明白它如何满足以下(看似)矛盾的情况。

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

表示“子类不继承其父类的私有成员。”

也就是说它既不继承私有实例变量也不继承私有方法对吧?

但是,如果它从其父级继承公共访问器方法,这将如何工作?它返回一个它不知道存在的实例变量?

此外,我的计算机科学书籍(Baron's AP Computer Science A)对“(子类)从(超类)继承所有私有实例变量和公共访问器方法”的问题提供了正确答案。

这不是oracle教程的缩影吗?

感谢您的帮助

【问题讨论】:

    标签: java inheritance encapsulation information-hiding


    【解决方案1】:

    访问器可以正常工作。请记住,访问器在超类的“上下文”中运行,因此访问器将能够看到对子类隐藏的成员。

    至于教科书,这取决于你的观点。子类继承了私有成员,因为它们实际上存在于子类的实例中(因此它们会占用内存等),但子类将无法直接访问它们。

    【讨论】:

    • +1 是的,你的答案可以通过一个例子来强调:人类继承了(如果我们相信进化论)猴子的某种尾巴(底部骨头的一部分),但他们可以不要摇尾巴。他们只能看着猴子摇他们的故事,或者给他们香蕉来鼓励他们摇他们的故事。
    • 这与私有方法的继承有何关系?它们是继承的但隐藏的吗?你不能使用(子类的对象)。(superclsas的私有方法)对吗?编辑:Lajos 就是一个很好的例子。
    • 这与尾巴是猴子的私有成员有关,摇尾巴是一种私有方法,因为只有猴子才有尾巴,也只有它们才能摇尾巴。但是,有两种方法:第一种是观察猴子尾巴的公共方法,它在基类(Monkey)中定义,人类也可以访问,人类也可以看到猴子摇摆不定的故事,而第二种是私下给猴子送香蕉的方法,只有人类才能接触到,因为猴子是自私的,他们不会互相给香蕉。
    • 我也给出了答案,你可以测试一下。
    • 而摇尾是猴子的私有方法?因此不会被人类遗传?
    【解决方案2】:

    把它想象成洋葱。层次结构的每一层都是洋葱中的一层。例如,如果 C 类扩展了 B 类,而 B 类扩展了 A 类,那么 C 类的对象将如下所示:

    Object of Class C

           -------------------------------------------------------------
           |                                                           | 
           |                   C and it's members                      |
           |                                                           |
           |    ------------------------------------------------       |
           |    |                                              |       |
           |    |              B and it's members              |       |
           |    |    ------------------------------------      |       |                                              
           |    |    |         A and it's members       |      |       |
           |    |    |                                  |      |       |
           |    |    ------------------------------------      |       |                                   
           |    ------------------------------------------------       |
           |                                                           |
           -------------------------------------------------------------            
    

    所以,C 类的对象确实有 B 和 A 的成员。但它不能访问 B 和 A 的私有成员。

    但是它可以访问 B 和 A 的公共和受保护成员。

    因此 B 或 A 的公共访问器函数将允许 C 类的此对象访问 B 类或 A 类的私有实例变量“部分”对象。

    【讨论】:

      【解决方案3】:

      这里的“不继承”意味着您无法访问它。它仍然存在,只是不能以任何方式与您交互(通过调用超类的非私有方法除外)。

      The accepted answer 在您链接到的问题中确实解释了这一点。该解释中是否有任何不明确的特定部分?

      【讨论】:

      • 不清楚的是为什么我的教科书说这是那个问题的答案。
      • 它只是意味着与“继承”略有不同。
      【解决方案4】:

      当然,当你创建一个类B的对象时,它继承自一个类A,如果类A有私有项,根据Java中的访问规则,你不能访问它们,但这些元素确实存在于私有内存中,如果它们是空对象,即使作为空引用也是如此。

      在Java 语言规范中,您可以阅读:

      类从其直接超类和直接超接口继承 超类和超接口的所有非私有字段 类中的代码都可以访问,并且不会被 类中的声明。

      超类的private 字段可能可供子类访问 - 例如,如果两个类都是同一个类的成员。 尽管如此,private 字段永远不会被子类继承。

      【讨论】:

        【解决方案5】:

        如果子类在同一个包中,它也继承私有成员,否则它只继承公共和受保护成员!

        【讨论】:

          【解决方案6】:

          私有成员也被继承。要对此进行测试,您可以在超类中执行以下操作:

          //...
          private String myText = "I'm in the superclass";
          
          private void setMyText(String myTextValue)
          {
              this.myText = myTextValue;
          }
          
          public void setMyTextPublic(String myTextValue)
          {
              setMyText(myTextValue);
          }
          
          public String getMyText()
          {
              return myText;
          }
          //...
          

          在继承的类中创建方法:

          //...
          public void setMyTextInTheSuperClass(String myTextValue)
          {
              System.out.println(getMyText());
              setMyTextPublic(myTextValue);
              System.out.println(getMyText());
          }
          
          public void setConstantValueToMyText()
          {
              setMyTextInTheSuperClass("I am in the child class");
          }
          //...
          

          然后在某处调用 setConstantValueToMyText。

          【讨论】:

          • 我完全支持元语法命名方案,但在某些时候它可能会变得复杂。您可能应该将 foobar 重命名为 setFoo 和 barfoo 重命名为 getFoo。
          • @Jeffrey,你指出命名问题是绝对正确的,但是测试代码中的命名是没有任何意义的,目的是为了展示操作,他可能是我们正在谈论的新手任何成员和任何函数,而不仅仅是设置或获取值。但是,当您谈到“不要在家里尝试这个,您的命名应该有意义”的这些命名时,您是对的。
          • 我认为大多数人都会有意识地不在实际代码中那样命名他们的方法,但是当我尝试按照您的示例进行操作时,我有点困惑。我只能想象对于初学者来说会有多混乱。
          • 很公平,代码被修改了。也许现在更有帮助。
          • 是的,你是对的。如果您尝试直接从继承的类中操作 myText,您的代码将无法编译。
          猜你喜欢
          • 2011-03-23
          • 1970-01-01
          • 1970-01-01
          • 2012-12-03
          • 2013-11-10
          • 1970-01-01
          • 2013-08-16
          • 2018-06-06
          • 1970-01-01
          相关资源
          最近更新 更多