子类是不是从超类继承私有实例变量

Posted

技术标签:

【中文标题】子类是不是从超类继承私有实例变量【英文标题】: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教程的缩影吗?

感谢您的帮助

【问题讨论】:

【参考方案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 重命名为 setFoobarfoo 重命名为 getFoo @Jeffrey,你指出命名问题是绝对正确的,但是测试代码中的命名是没有任何意义的,目的是为了展示操作,他可能是我们正在谈论的新手任何成员和任何函数,而不仅仅是设置或获取值。但是,当您谈到“不要在家里尝试这个,您的命名应该有意义”的这些命名时,您是对的。 我认为大多数人都会有意识地不在实际代码中那样命名他们的方法,但是当我尝试按照您的示例进行操作时,我有点困惑。我只能想象对于初学者来说会有多混乱。 很公平,代码被修改了。也许现在更有帮助。 是的,你是对的。如果您尝试直接从继承的类中操作 myText,您的代码将无法编译。

以上是关于子类是不是从超类继承私有实例变量的主要内容,如果未能解决你的问题,请参考以下文章

从超类对象初始化子类实例

当子类被实例化时,超类的私有成员是不是也被实例化? [复制]

Java基础-继承

Subclass构造函数是否从Superclass构造函数继承变量?

如何使子类只能从实例访问?

Python子类方法从超类方法继承装饰器