怎么用super调用超类构造函数?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
简介: Java 中的 `super` 关键字用于子类引用父类的构造函数和成员。当子类构造函数需要调用父类的构造函数时,`super` 须作为第一条语句,如 `super(param列表);`,这允许子类初始化父类的属性。示例中,`BoxWeight` 类通过 `super(w, h, d)` 调用 `Box` 的构造函数来设置尺寸,而 `BoxWeight` 自己仅设置重量。`super` 也可用于访问被子类隐藏的父类成员,实现封装。

从Box派生的类并没有体现出它们的实际上是多么有效和强大。例如,BoxWeight构造函数明确的初始化了Box( )的width、height和depth成员。

这些重复的代码在它的超类中已经存在,这样做效率很低,而且,这意味着子类必须被同意具有访问这些成员的权力。然而,有时你希望创建一个超类,该超类可以保持它自己实现的细节(也就是说,它保持私有的数据成员)。这种情况下,子类没有办法直接访问或初始化它自己的这些变量。既然封装是面向对象的基本属性,Java提供了该问题的解决方案是不值得奇怪的。

任何时候一个子类需要引用它直接的超类,它可以用关键字super来实现。super有两种通用形式。第一种调用超类的构造函数。第二种用来访问被子类的成员隐藏的超类成员。下面分别介绍每一种用法(第二种下个文章中介绍)。

使用super调用超类构造函数子类可以调用超类中定义的构造函数方法,用super的下面形式:

java

复制代码

super(parameter-list); 

这里,parameter-list定义了超类中构造函数所用到的所有参数。super( )必须是在子类构造函数中的第一个执行语句。为了了解怎样运用super( ),考虑下面BoxWeight( )的改进版本:

java

复制代码

// BoxWeight now uses super to initialize its Box attributes. 
class BoxWeight extends Box { 
 double weight; // weight of box 
 // initialize width, height, and depth using super() 
 BoxWeight(double w, double h, double d, double m) { 
 super(w, h, d); // call superclass constructor 
 weight = m; 
 } 
}

这里,BoxWeight( )调用带w、h和d参数的super( )方法。这使Box( )构造函数被调用,用w、h和d来初始化width, height, 和 depth。BoxWeight不再自己初始化这些值。它只需初始化它自己的特殊值:weight。这种方法使Box可以自由的根据需要把这些值声明成private。

上面的例子,调用super( )用了三个参数。既然构造函数可以被重载,可以用超类定义的任何形式调用super( ),执行的构造函数将是与所传参数相匹配的那一个。

例如,下面是BoxWeight一个完整的实现,BoxWeight具有以不同方法构造盒子的构造函数。在每种情况下,用适当的参数调用super( )。注意width, height, and depth在Box是私有的。

java

复制代码

// A complete implementation of BoxWeight. 
class Box { 
 private double width; 
 private double height; 
 private double depth; 
 // construct clone of an object 
 Box(Box ob) { // pass object to constructor 
 width = ob.width; 
 height = ob.height; 
 depth = ob.depth; 
 } 
 // constructor used when all dimensions specified 
 Box(double w, double h, double d) { 
 width = w; 
 height = h; 
 depth = d; 
 } 
 // constructor used when no dimensions specified 
 Box() { 
 width = -1; // use -1 to indicate 
 height = -1; // an uninitialized 
 depth = -1; // box 
 } 
 // constructor used when cube is created 
 Box(double len) { 
 width = height = depth = len; 
 } 
 // compute and return volume 
 double volume() { 
 return width * height * depth; 
 } 
} 
// BoxWeight now fully implements all constructors. 
class BoxWeight extends Box { 
 double weight; // weight of box 
 // construct clone of an object 
 BoxWeight(BoxWeight ob) { // pass object to constructor 
 super(ob); 
 weight = ob.weight; 
 } 
 // constructor when all parameters are specified 
 BoxWeight(double w, double h, double d, double m) { 
 super(w, h, d); // call superclass constructor 
 weight = m; 
 } 
 // default constructor 
 BoxWeight() { 
 super(); 
 weight = -1; 
 } 
 // constructor used when cube is created 
 BoxWeight(double len, double m) { 
 super(len); 
 weight = m; 
 } 
} 
class DemoSuper { 
 public static void main(String args[]) { 
 BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3); 
 BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076); 
 BoxWeight mybox3 = new BoxWeight(); // default 
 BoxWeight mycube = new BoxWeight(3, 2); 
 BoxWeight myclone = new BoxWeight(mybox1); 
 double vol; 
 vol = mybox1.volume(); 
 System.out.println("Volume of mybox1 is " + vol); 
 System.out.println("Weight of mybox1 is " + mybox1.weight); 
 System.out.println(); 
 vol = mybox2.volume(); 
 System.out.println("Volume of mybox2 is " + vol); 
 System.out.println("Weight of mybox2 is " + mybox2.weight); 
 System.out.println(); 
 vol = mybox3.volume(); 
 System.out.println("Volume of mybox3 is " + vol); 
 System.out.println("Weight of mybox3 is " + mybox3.weight); 
 System.out.println(); 
 vol = myclone.volume(); 
 System.out.println("Volume of myclone is " + vol); 
 System.out.println("Weight of myclone is " + myclone.weight); 
 System.out.println(); 
 vol = mycube.volume(); 
 System.out.println("Volume of mycube is " + vol); 
 System.out.println("Weight of mycube is " + mycube.weight); 
 System.out.println(); 
 } 
}

该程序产生下面的输出:

java

复制代码

Volume of mybox1 is 3000.0 
Weight of mybox1 is 34.3 
Volume of mybox2 is 24.0 
Weight of mybox2 is 0.076 
Volume of mybox3 is -1.0 
Weight of mybox3 is -1.0 
Volume of myclone is 3000.0 
Weight of myclone is 34.3 
Volume of mycube is 27.0 
Weight of mycube is 2.0 

特别注意BoxWeight( )中的这个构造函数:

java

复制代码

// construct clone of an object 
BoxWeight(BoxWeight ob) { // pass object to constructor 
 super(ob); 
 weight = ob.weight; 
} 

注意super( )被用一个BoxWeight类型而不是Box类型的对象调用。这仍然调用了构造函数Box(Box ob)。前面已经提醒过,一个超类变量可以引用作为任何一个从它派生的对象。

因此,我们可以传递一个BoxWeight对象给Box构造函数。当然,Box只知道它自己成员的信息。

让我们复习super( )中的关键概念。当一个子类调用super( ),它调用它的直接超类的构造函数。这样,super( )总是引用调用类直接的超类。这甚至在多层次结构中也是成立的。

还有,super( )必须是子类构造函数中的第一个执行语句。

转载来源:https://juejin.cn/post/6898602429468672014

相关文章
|
10月前
|
C#
C# 继承类中(父类与子类)构造函数的调用顺序
C# 继承类中(父类与子类)构造函数的调用顺序
|
存储 Java C#
【c#入门杂选】重载,继承,委托
【c#入门杂选】重载,继承,委托
87 0
|
Python
python调用父类方法的三种方式(super调用和父类名调用)
python调用父类方法的三种方式(super调用和父类名调用)
196 0
|
Java 程序员 C++
java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)
java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)
184 0
java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)
|
Java 编译器
java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(2)
java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(2)
126 0
java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(2)
|
前端开发 开发者
class-子类访问父类上的实例方法|学习笔记
快速学习 class-子类访问父类上的实例方法
90 0
C#(二十一)之派生类中的构造函数 object类
今天看下派生类中的有参数和无参数的构造函数以及object类。
122 0
C#(二十一)之派生类中的构造函数 object类
|
Kotlin
【Kotlin】Kotlin 类的继承 三 ( super 关键字使用 | super@ 外部调用父类方法 | 子类选择性调用 父类 / 接口 方法 super )
【Kotlin】Kotlin 类的继承 三 ( super 关键字使用 | super@ 外部调用父类方法 | 子类选择性调用 父类 / 接口 方法 super )
739 0
|
Kotlin
【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )(一)
【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )(一)
257 0
|
Kotlin
【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )(二)
【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )(二)
145 0