OOP 和私有字段的继承

Posted

技术标签:

【中文标题】OOP 和私有字段的继承【英文标题】:OOP and inheritance of private fields [closed] 【发布时间】:2016-02-16 09:05:45 【问题描述】:

在 C# 中,规范说:

实例构造函数、析构函数和静态构造函数不是 继承的,但所有其他成员都是,不管他们的声明 可访问性(第 3.5 节)。但是,根据他们声明的 可访问性,继承的成员可能无法在派生的 类。

因此私有字段被继承到派生类中,但它们不可访问。

但是 Java 规范说:

只有声明为受保护或公共的类的成员才是 由包中声明的子类继承,而不是 声明了哪个类。

所以私有字段不会被继承到派生类中。

什么解释了 OOP 理论?是正确的 C# 还是 Java 设计者?

在这方面有点困惑。

附: 我没有C++经验? C++ 设计师对此有何看法?

【问题讨论】:

没有 OOP 理论。 OOP 是一种通用的概念/编程风格,不同的语言可能以不同的方式支持它。你甚至可以用纯 C 语言做 OOP。 【参考方案1】:

嗯,C# 版本是 more-clear 因为即使在 Java 中,私有字段也可以作为子对象的一部分使用,但它们不能直接访问,除非您在父类中有一个公共 getter 来获取它的值。

您实际上可以使用反射来使(父级的)私有字段可访问并直接读取它们的值。

【讨论】:

如何证明在 Java 中私有字段也被继承了?我认为规范是官方文件,它说不要! @xdevel2000 - 如果您在父级中有私有字段的公共 getter 怎么办?.. 该方法将在子级中返回什么?如果该值甚至不存在,那么实际上允许继承公共方法的意义何在? 重点是没有公共字段。关键是派生类是否继承了私有成员,但它却不可访问。 @xdevel2000 你可以使用反射来检查你的类并查看这些字段是否仍然存在。 @xdevel2000 - 是的,这就是重点。派生类具有无法访问的数据(私有字段)。【参考方案2】:

保持事情简单明了,引用你提到的 c++ 引用的一部分

但是,根据声明的可访问性,继承的成员可能无法在派生类中访问。

同样的事情也发生在 Java 中。你也不能访问 Java 中的私有字段。

它们周围有方法可以访问这是另一个故事(封装)

【讨论】:

【参考方案3】:

至少回答 C#/Java 部分,因为我对 C++ 了解不多。

但是,根据声明的可访问性,继承的成员可能无法在派生类中访问。

C# 规范似乎更有意义,尽管 Java 以相同的方式处理私有成员。来自基类的私有成员在 Java 中也存在(但它们不是继承,请参阅are private fields inherited in Java?)。由于您无法访问它们,因此无论如何这都没有用。然而,内部当然也是通过设置私有成员来初始化的。因此,您的派生类的实例当然具有基类的所有私有成员,inheritance 但是意味着任何类型的多态性,这意味着您可以覆盖(假设您的会员不是staticfinal/selead) 他们,这对私人会员毫无意义。

因此,我们根本不需要访问内部结构,无论是在 C#、Java 还是其他任何地方。只需假设您的派生实例已完全初始化所有基本成员并执行您的实际工作。

关于你所谓的“OOP 理论”,我怀疑对于这个 原则(在上述语言中以不同的方式实现)私人成员根本没有相关性. OOP 仅处理对象与其周围环境之间的交互,而不是它们的实际内部。

【讨论】:

【参考方案4】:

我认为这种混淆与令人困惑的措辞有关。在 Java 或 C# 或任何其他 OO 语言中,如果您构造一个子项,则必须调用父级构造函数,因为父项是子项的一部分。很多时候,父构造函数的调用是隐式完成的。

所以来自父对象的私有属性总是存在于子对象的某个地方。然后 OOP 确保您无法访问子级中的私有属性。这个封装很重要。这个事实是由两个参考文献描述的:要么你称之为属性不被继承,要么你说它们被继承但不可见

如上所述,您可以(ab)使用反射库来绕过这些限制。

【讨论】:

以上是关于OOP 和私有字段的继承的主要内容,如果未能解决你的问题,请参考以下文章

php面向对象特性

为啥子类继承私有字段?

PHP OOP的特性-封装

PHP OOP 面向对象的特性

java中字段继承问题--子类不能继承父类的私有成员

C# 类继承中的私有字段都去了哪里?