2

我很好奇“继承”的概念是如何在面向对象编程的世界中发生的。让我解释一下我的困境(我在学习 Java 时遇到了这个困境,但我希望我的问题本质上是通用的):

假设有一个 A 类和一个 B 类。A 类“继承” B 类。这实际上是什么意思?编译器是否创建了一个“新”类,然后将其实例化为一个对象,该对象在幕后包含类 A 和 B 的元素?如果是这样的话,那么访问限制是如何根据访问说明符实现的呢?

有那么一刻,我想知道它是否以以下方式发生:

创建一个 A 类的对象,然后创建一个 B 类的对象。Java 然后以某种方式将 A 的成员“链接”到 B 的成员,并使其看起来好像它们属于同一个类,并且它根据访问说明符进行操作。

但后来,我突然想到这个理论有问题。假设两个不同的类,B 和 C 继承类 A。那么,如果我们要创建 B 类和 C 类的对象,那么它们将拥有 A 类元素的 OWN 副本。所以这个理论也失败了。

我只是想解释一下我心中对继承的困惑。这让我很头疼。请帮忙。

编辑:这是我在本网站上找到的与我的问题相关的讨论的链接。

子类是否继承私有字段?

4

2 回答 2

2

我可能会失败,但我会为你解释一下。

老实说,我认为你在构思对象编程时可能犯了一个非常经典的错误——那就是区分对象。几乎任何面向对象语言中的对象创建都是基于类定义的构造之一。从您的问题来看,这听起来好像您在心理上建模一种 OO 语言,特别是对象继承作为聚合离散对象,实际上这些对象是根据聚合定义定义的。

public class A
{
    public A();
}

public class B:A
{
    public B();
}

public class C:B
{
    public C();
}

在您的 A->B->C 模型中,C 的定义是根据它自己的独特属性加上它的直系祖先 B 的所有成员,而 B 又是根据它自己的独特属性加上所有成员来定义的它的直接祖先 A. 创建对象的过程仍然是一个独特且离散的事件,并且该对象尽管具有多层遗产,但在实例化时仍然只是一个对象

关于某些成员的可见性:当一个类作者设计和构建一个类时,他会从两个不同的角度对他提供的内容做出某些决定:向类的消费者公开的内容,以及对子类公开或可用的内容. 声明为私有的成员和字段都是后代类的一部分,即使它们“合同”禁止被子类访问。您可以粗略地类比,电视具有开/关按钮、音量控制和颜色控制的“公共”界面,但具有不针对消费者的“内部”控制,例如内部电子元件或电源供应。即使它们对消费者或子类不“可见”或“可用”,它们仍然非常存在。

现在,也就是说,大多数 OO 语言中的构造反映了您描述的属性 - 多个对象 - 并且涉及称为组合(或者,有时是Aggregation )的设计模式。这是一个类不是从祖先派生的地方类 - 通常是因为该类被声明为“密封”(C#)或“最终”(Java)(或其他禁止继承的名称)。这迫使有兴趣使用该类的开发人员使其成为另一个类的成员,例如当类的对象被实例化时,你确实两个类的离散对象

您可能有以下情况:

public final class InterestingThing
{
    //definitions
    public InterestingThing()
}

public final class MyThing
{
    InterestingThing _interestingThing = new InterestingThing();

    public MyThing()
}

这与您在原始问题中所描述的场景非常相似,其中 MyThing 的创建暗示了InterestingThing 的独特创建。请记住,这种结构通常也是由感兴趣的原始类的设计和定义所强制的。

归根结底,对象是由它们的类定义的,多重继承的类仍然只是一个类,但是在一个基于良好的增量对象设计的精致的、希望越来越健壮的层次结构中。

我希望,在某种程度上,这个解释有助于回答你的问题。

于 2012-09-22T19:03:21.460 回答
1

A 类“继承”B 类。这实际上是什么意思?

如果类 A 扩展类 B,它继承 B 的所有成员(字段和方法),即类 A 将拥有这些成员,即使它们没有在类 A 的主体中声明。

是否允许 A 类访问特定成员是不相关的事情。

创建一个 A 类的对象,然后创建一个 B 类的对象。Java 然后以某种方式将 A 的成员“链接”到 B 的成员,并使其看起来好像它们属于同一个类,并且它根据访问说明符进行操作。

不,A 类的单个对象被创建。该对象恰好也具有所有继承的成员。例如,如果您有:

class B {
    private int x;
}

class A extends B {
    private int y;
}

运行时将为类 A 的每个对象存储 的值x和 的值y

x通过验证 A 的源代码在编译时不使用该名称,并通过验证 A 的字节码在运行时加载类时x不引用字段来强制执行类 A 中的代码不访问值。x换句话说,访问修饰符独立于内存布局。

于 2012-09-22T19:36:45.567 回答