5.3.1 有继承时的构造方法
子类不能继承父类的构造方法,但子类的构造方法与父类的构造方法存在着一定的关系,并遵守下列原则。
(1)如果子类没有定义任何构造方法,那么在创建子类对象时,调用父类无参构造方法(即默认的构造方法),即执行super();。
(2)如果子类定义了构造方法,并且在子类构造方法中没有显式调用父类的构造方法,那么在创建子类对象时,首先调用父类无参构造方法(即默认的构造方法),然后再执行子类自己的构造方法。
(3)如果子类定义构造方法,并且在子类构造方法中利用super关键字显式调用父类的构造方法,那么在创建子类对象时,首先执行显式调用父类的构造方法,然后再执行子类构造方法体的其余部分。不再调用父类无参构造方法(即默认的构造方法)。
注意:super显式调用语句必须放在子类构造方法的第一个可执行语句。
【例5-5】 有继承时,子类中构造方法的举例。
程序运行结果:
分析与思考:(1)在子类中,构造方法体中的第一条语句可以是对直接超类中的一个构造方法的显式调用,格式为:
super([实参表]);
例如本例中的super(r);和super(obj.radius);。
在子类中,构造方法体中的第一条语句也可以是调用同类中的另一个构造方法,其格式是:
this([实参表]);例如本例中的this(0);、this(0.0,0.0);、this(r,0.0);和this(obj,0.0);。
在子类中,如果构造方法体中的第一条语句既不是super语句又不是this语句,那么隐含执行父类无参构造方法,即执行super();。
(2)在类中可以定义多个构造方法。构造方法越多,说明创建对象的手段就越多。因此,在创建这个类对象时,就可以根据不同情况选择不同的构造方法。如o1选择Cylinder()构造方法,o3选择Cylinder(3,4)构造方法,o5选择Cylinder(obj2,5)构造方法。
(3)当创建一个类的对象时,该类及其所有超类,每个类都至少有一个构造方法被调用。而且调用构造方法的次序是超类的构造方法执行完后,才能执行子类的构造方法。如o1、o2、o3、o4、o5这5个对象的创建,都是先调用Circle构造方法,再调用Cylinder构造方法。
模仿例5-5:长方体类是矩形类的子类,使用重载构造方法实现长方体类,并测试它。
小结 下面是对象初始化一般过程的描述:
(1)创建所有的实例变量(包括超类中定义的)并设置为默认的初值。
(2)选择构造方法、创建参数变量并赋值。
(3)如果该构造方法以对同一类另一个构造方法的显式调用开始,则重复第(2)步~第(6)步递归处理那个构造方法调用。之后继续第(6)步。
(4)如果该构造方法不是Object类的构造方法,则以对直接超类的一个构造方法的调用开始,此时重复第(2)~(6)步递归处理超类中那个构造方法调用。之后继续第(5)步。
(5)按照在程序正文中出现的先后次序,计算实例变量定义语句中的初始化表达式并赋值,或者执行实例初始化块中的语句。
(6)执行构造方法体的其余部分。
根据这一过程,可以得出以下结论:
·当创建一个类的对象时,该类及其所有超类,每个类都至少有一个构造方法被调用。
·Object类的构造方法首先被执行,一个类的构造方法仅在它的超类中的构造方法被执行后才被执行。
·每个实例变量初始化表达式被严格计算一次,在计算一个初始化表达式时,其超类中的所有实例变量初始化表达式已被计算,超类中的构造方法也已被执行,而其所在类的构造方法的具体代码还没有被执行。
【例5-6】 有继承时,对象初始化举例。
程序运行结果如下:
分析与思考:程序运行结果充分体现了,创建对象时对象初始化的完整过程。在创建obj对象时,首先创建所有的实例变量,并设置为默认值,即radius=0.0;height=0.0;,然后计算父类初始化表达式radius=10;执行父类构造方法,再计算子类初始化表达式height=50;执行子类构造方法,如图5-1所示。
图5-1 实例变量初始化的过程
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。