使用 super 调用父类构造函数

💡 原文约300字/词,阅读约需1分钟。
📝

内容提要

子类可以使用super()调用其父类定义的构造函数。super()的参数列表应指定父类构造函数所需的参数。子类构造函数中的第一条语句应始终是super()(或super(参数列表)),以便传递参数。使用super()允许父类根据需要构建其自己的子对象并添加功能,而无需子类了解细节。可以使用super()调用父类定义的任何构造函数。调用的构造函数将是与提供的参数相匹配的构造函数。

🔎

延伸解读

为什么 super() 必须是构造函数的第一条语句

文章强调,子类构造函数中的第一条执行语句必须是 super() 或 super(参数列表)。这并非语法上的随意规定,而是为了确保父类部分在子类自己的初始化代码运行之前已经完成构建。如果先执行子类代码,可能会访问尚未初始化的父类成员,导致不可预期的行为。因此,这条规则是对象初始化顺序的硬性保障。

super() 如何简化子类职责

以 Triangle 和 TwoDShape 为例,Triangle 的构造函数只需初始化自己特有的 style 字段,而 width 和 height 完全交给父类 TwoDShape 的构造函数处理。通过 super(w, h) 传递参数,子类无需知道父类内部如何设置这些值。这种分工让父类可以独立修改自己的初始化逻辑,而子类代码不受影响,降低了耦合。

super() 始终指向直接父类

文章明确指出,super() 引用的是当前类的直接父类,即使处于多层继承体系中也是如此。这意味着如果存在 A → B → C 的继承链,在 C 的构造函数中调用 super() 只会调用 B 的构造函数,而不会跳过 B 直接调用 A。理解这一点有助于正确设计多层继承中的初始化流程,避免误以为 super() 会调用最顶层的祖先类。

如何选择要调用的父类构造函数

父类可能定义了多个构造函数,子类通过 super() 调用哪一个,取决于传入的参数列表。文章说明,执行的构造函数将是与提供的参数相匹配的那一个。因此,子类在编写 super(...) 时,必须根据父类构造函数的参数类型和数量来传递正确的实参。这要求子类作者了解父类提供了哪些构造函数签名,但不需要知道其内部实现细节。

❓

Q&A

如何在子类中使用super()调用父类构造函数?

在子类构造函数中,第一条语句应始终是super()或super(参数列表),以调用父类构造函数并传递必要的参数。

super()的参数列表需要包含什么?

参数列表应指定父类构造函数所需的参数,以便正确初始化父类的属性。

使用super()有什么好处?

使用super()允许父类构建自己的子对象并添加功能,而无需子类了解实现细节。

在多层次继承中,super()引用的是哪个类?

super()引用的是直接父类,即使在多层次的继承中也是如此。

Triangle类是如何使用super()的?

Triangle类使用super(w, h)调用父类TwoDShape的构造函数,传递宽度和高度的值。

为什么super()必须是子类构造函数中的第一条语句?

super()必须是第一条语句,以确保父类部分被初始化,之后才能执行子类的构造代码。

🏷️

标签

➡️

继续阅读