在 Java 程序中,继承描述了类的所属关系,多个类通过继承可形成一个关系体系,进而在原有类的基础上派生出新的类,扩展新的功能,从而实现代码的复用。
采用继承机制来设计软件系统中的类,可以提高程序的抽象程度,减少程序维护工作量,提高开发效率。
Java继承的概念
在现实生活中,“继承”是指按照法律或遵照遗嘱接受死者的财产、职务、头衔、地位等;在 Java 程序中,继承指的是指一个对象直接使用另一对象的属性和方法。
图 1 Car类、Bus类和Truck类的关系图
如上图所示,卡车(Truck类)和公交车(Bus类)都属于汽车(Car类),它们都有发动机(engine)和轮子(wheel),都可以行驶(run)和刹车(stop),但是卡车类新增了载重量(capacity)属性以及拉货(load)和卸货(unload)方法,公交车类新增了载客量(capacity)属性以及报站(busstop)和停靠(dock)方法。
在面向对象程序设计中,一个新类从已经存在的类中获得成员变量或成员方法,这种现象称为继承。提供继承信息的类被称为父类(超类、基类),得到继承信息的类被称为子类(派生类)。
一个父类可以同时拥有多个子类,但 Java 语言不支持多重继承,所以一个类只能有一个父类。父类是所有子类的公共成员变量和成员方法的集合,而子类是父类的特例,子类继承父类的成员变量和成员方法,可以修改父类的成员变量或重写父类的成员方法,也可以增加新的成员变量或成员方法。
采用继承机制来设计系统中的类,可以提高程序的抽象程度,更加接近于人类的思维方式。
继承机制的显著特点之一是可以实现代码复用。例如,下面有一个 Dog 类和 Cat 类:
class Dog {
private String name; // 声明名字属性
private int age; // 声明年龄属性
public void show() { // 定义显示信息的方法
System.out.println("狗" + name + "在啃骨头");
}
}
class Cat {
private String name; // 声明名字属性
private int age; // 声明年龄属性
public void show() { // 定义显示信息的方法
System.out.println("猫" + name + "在吃咸鱼");
}
}
仔细观察这段代码我们会发现,在 Dog 类和 Cat 类中有很多重复代码,假设我们后续增加 Pig 类、Monkey 类等,重复代码还会不断增加。这时候,我们就可以提取这些类的相同成员变量和成员方法,设计一个 Anima(动物类),使 Dog 类、Cat 类等继承 Animal 类。
Java继承的使用
在 Java 语言中,类的继承通过 extends 关键字来实现,在定义类时通过 extends 关键字指出新定义类的父类,表示在两个类之间建立了继承关系。新定义的类称为子类,它可以从父类那里继承所有非 private(私有)的成员。
Java 继承的语法格式如下:
class 子类A extends 父类B {
// 代码块
}
该语法表示子类 A 派生于父类 B,如果类 B 又是某个类的子类,则类 A 同时也是该类的间接子类。
如果没有 extends 关键字,则该类默认为 java.lang.Object 类的子类。Java 语言中的所有类都是直接或间接地继承 java.lang.Object 类得到的,所以之前所有案例中的类均是 java.lang.Object 类的子类。
接下来,通过案例来演示如何通过继承 Animal 类来派生 Dog 类、Cat 类,从而形成类的继承体系,实现代码复用。
class Animal { // 定义父类Animal类
public String name;
public int age;
public void show() {
System.out.println("名字是" + name + ", 年龄: " + age);
}
}
class Dog extends Animal { // 定义子类Dog类
String color;
public void eat() {
System.out.println(color + "的狗狗在啃骨头");
}
}
class Cat extends Animal { // 定义子类Cat类
}
public class Demo {
public static void main(String[] args) {
Dog d = new Dog();
d.name = "旺财";
d.age = 3;
d.color = "黑色";
d.show();
d.eat();
}
}
程序的运行结果如下:
名字是旺财,年龄:3
黑色的狗狗在啃骨头
程序中,Dog 类通过 extends 关键字继承了 Animal 类,它就是 Animal 的子类,Cat 类同样如此。
从程序运行结果中可发现,Dog 类虽然没有定义 name、age 成员变量和 show() 成员方法,但却能访问这些成员,说明子类可以继承父类所有的成员。