6.2.2 继承的实现

6.2.2 继承的实现

用关键字extends来实现从超类继承一个类,或者说,扩展超类的功能。

语法:[访问权限] class <子类类名> extends <超类类名>

说明:“访问权限”是指public,private等;“extends”是继承关键字,extends后面跟的为超类类名。

例如:public class Sub1 extends Super

img201

1.子类继承的成员变量

子类继承超类中所有可被子类访问的成员变量。继承原则如下:

img202 能够继承那些声明为public和protected的成员变量。

img203 能够继承同一包中的那些默认修饰符的成员变量。

img204 不能继承那些声明为private的成员变量。

如果子类声明一个与超类成员变量同名的成员变量,则不能继承超类的成员变量。此时子类的成员变量称为隐藏了超类的成员变量。

总之,子类只能继承超类中非私有的成员变量。

因此,若超类不允许其子类访问它的某些成员,那么这些成员变量必须以private方式声明该成员;若超类只允许其子类访问、不允许其他类访问的成员变量,那么这些成员变量必须以public修饰符声明该成员变量。这正好是类封装的信息隐蔽原则的充分体现。

2.子类继承的成员方法

子类继承超类方法的规则类似于继承成员变量的规则。继承原则如下:

img205 能够继承那些声明为public和protected的成员方法。

img206 能够继承同一包中的那些默认修饰符的成员方法。

img207 不能继承那些声明为private的成员方法。

img208 不能继承超类的构造方法。

如果子类方法与超类方法同名,则不能继承。子类方法称为覆盖了超类中的那个方法。

总之,子类只能继承超类中非私有的成员方法。

因此,若超类不允许其子类访问它的某些成员,那么这些成员方法必须以private方式声明该成员;若超类只允许其子类访问、不允许其他类访问的成员方法,那么这些成员方法必须以Protected修饰符声明该成员方法。

子类除了可以继承超类中的变量及方法,还可以增加自己的成员。当一个超类成员不适合该子类时,子类会以恰当的方式重新定义它,就是隐藏超类的变量、覆盖超类的方法。

3.this引用

Java中,每个对象都具有对其自身引用的访问权,称为this引用。this引用是作为非static方法调用中的隐含参数传递到对象中的。这样,当对象的任何非static方法运行时,该方法具有对this引用的访问权。

this表示的是当前对象本身,更准确地说,this代表了当前对象的一个引用。对象的引用可以理解为对象的另一个名字,通过引用可以顺利地访问对象,包括修改对象的属性、调用对象的方法。

this引用的使用规则如下:

(1)指代对象本身。格式为:

img209

例如,下面的方法equals()比较两个对象obj1,obj2是否相等。其中obj2对象通过参数传递值,obj1对象是隐藏的。在方法中,通过this引用,指代调用本方法的当前对象。

img210

(2)访问本类的成员变量和成员方法。格式为:

img211

例如,下面定义的类XXX中有成员变量a,而在方法DDD中也用a作参数,这样两个不同含义的变量a就有可能混淆,此时必须用this.a指代对象的成员变量a。

img212

(3)调用本类的构造方法。格式为:

img213

4.super引用

java中通过super来实现对超类成员的访问,super用来引用当前对象的超类。super的使用有三种情况:

1)访问被子类隐藏的超类的成员变量和成员方法,格式为:

img214

2)调用父类的构造函数,格式为:

img215

5.成员变量的隐藏和方法的覆盖

子类通过隐藏超类的成员变量和覆盖超类的方法,可以把超类的状态和行为改变为自身的状态和行为。如果子类声明一个与超类成员变量同名的成员变量,则不能继承超类的成员变量。此时子类的成员变量称为隐藏了超类的成员变量。

方法的覆盖是指:子类定义同名方法来覆盖超类的方法,是多态技术的一个实现。当超类方法在子类中被覆盖时,通常是子类版本调用超类版本,并做一些附加的工作。关于覆盖应注意的事项:

(1)不使用super而希望引用父类方法会导致无限的递归,因为子类方法实际上是在调用它自己。

(2)当通过父类引用调用一个方法时,Java会正确地选择与那个对象对应的类的覆盖方法。

(3)方法覆盖中,子类在重新定义父类已有的方法时,应保持与父类完全相同的方法头声明,即与父类完全相同的方法名、返回值和参数列表。

(4)子类可以添加字段,也可以添加方法或者覆盖父类中的方法。然而,继承不能去除父类中的任何字段和方法。例如:

img216

img217

方法重载和方法的覆盖是两个不同的概念,在软件设计中实现的功能也不同。

子类中覆盖的方法和父类中被覆盖的方法要具有相同的名字,相同的参数表和相同的返回类型,只是函数体不同。

而方法重载可以用相同的方法名但不同的参数表来定义方法(参数表中参数的数量、类型或次序有差异)。重载(overloading):当多个方法具有相同的名字而含有不同的参数时,便发生重载。编译器必须挑选调用哪个方法。它通过将在不同方法头部中的参数类型和在特定的方法调用中使用值的类型进行比较,从而挑选出正确的方法。

6.构造方法的继承

子类不仅可以继承超类的非私有的成员变量和方法,而且可以继承超类的构造方法,构造方法的继承遵循的原则是:

1)子类可以无条件地继承超类不含参数的构造方法。

2)如果子类没有构造方法,则它继承超类无参数的构造方法作为自己的构造方法;

若子类有构造方法,那么在创建子类的对象时,则将先执行继承下来的超类的构造方法,然后再执行自己的构造方法。

3)对于超类中包含有参数的构造方法,子类可以通过在自己的构造方法中使用super关键字来引用,而且必须是子类构造方法中的第一条语句。

7.超类对象与子类对象的使用与转化

超类对象与子类对象的转化需要注意如下的原则:(1)子类对象可以被视为是其超类的一个对象;(2)超类对象不能当成是其某一个子类的对象;(3)如果一个方法的形式参数定义的是超类对象,那么调用这个方法时,可以使用子类对象作为形式参数;(4)如果超类对象引用指向的实际是一个子类对象,那么这个超类对象的引用可以用强制类型转换转化成子类对象的引用。