单继承与多层继承
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 25 课,共 87 课。
到目前为止,我们已经看到类直接继承一个父类。但根据类之间的关系,继承可以形成不同的结构。让我们来了解两种主要模式:单继承和多级继承。
单继承是我们一直在使用的方式。一个类直接继承且只继承一个父类:
public class Animal { }
public class Dog extends Animal { }
public class Cat extends Animal { }这里,Dog 和 Cat 都继承自 Animal,但它们彼此之间没有继承关系。每个子类都有一个直接父类。
多层继承会形成一个链条:一个类继承另一个类,而后者本身又继承另一个类:
public class Animal {
public void eat() {
System.out.println("Eating");
}
}
public class Mammal extends Animal {
public void breathe() {
System.out.println("Breathing");
}
}
public class Dog extends Mammal {
public void bark() {
System.out.println("Barking");
}
}在这个继承链中,Dog 继承自 Mammal,而 Mammal 继承自 Animal。Dog 对象可以访问整个继承链中的所有方法:
Dog dog = new Dog();
dog.eat(); // 来自 Animal 类
dog.breathe(); // 来自 Mammal 类
dog.bark(); // 来自 Dog 类记住,Object 位于每条继承链的顶端。因此,我们的 Dog 实际上有四个层级:Object -> Animal -> Mammal -> Dog。创建新对象时,构造函数链式调用会经过所有这些层级。
挑战
简单让我们构建一个交通工具继承层级,展示单继承和多级继承模式。你将创建一系列类,每一层都会增加新功能,展示方法如何通过多个层级继承。
你需要将代码分布在四个文件中:
Vehicle.java:创建继承层级顶端的基类。每种交通工具都应具有:- 一个用于存储
brand(String)的私有字段 - 一个接收品牌名称的构造函数
- 一个返回品牌名称的方法
getBrand() - 一个输出
[brand] is moving的方法move()
- 一个用于存储
LandVehicle.java:创建一个继承自 Vehicle 的类,作为多级继承链的中间层。陆地交通工具会增加地面行驶相关的行为:- 一个用于存储
wheels(int)的私有字段 - 一个接收品牌名称和车轮数的构造函数,并使用
super(brand)初始化父类部分 - 一个返回车轮数的方法
getWheels() - 一个输出
[brand] honks!的方法honk()
- 一个用于存储
Car.java:创建一个继承自 LandVehicle 的类,完成三层继承链。汽车会增加自己的专属功能:- 一个用于存储
model(String)的私有字段 - 一个接收品牌名称、车轮数和型号的构造函数,并使用
super(brand, wheels) - 一个返回型号的方法
getModel() - 一个输出
[brand] [model] with [wheels] wheels的方法displayInfo()
- 一个用于存储
Main.java:演示 Car 对象如何调用继承层级三个层次中的方法。你会收到三个输入:品牌名称(String)、车轮数(int)和型号(String)。创建一个 Car,并按顺序调用以下方法:move():从 Vehicle(祖父类)继承honk():从 LandVehicle(父类)继承displayInfo():在 Car 类自身中定义
你会收到三个输入:品牌名称、车轮数和型号。
你的输出应包含三行,展示 Car 对象如何使用继承链每一层中的方法,从最顶层的 Vehicle 一直到它自身的类!
亲手试试
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入
String brand = scanner.nextLine();
int wheels = scanner.nextInt();
scanner.nextLine(); // 读掉换行符
String model = scanner.nextLine();
// TODO: 用输入值创建一个 Car 对象
// TODO: 调用 move(),它继承自 Vehicle(祖父类)
// TODO: 调用 honk(),它继承自 LandVehicle(父类)
// TODO: 调用 displayInfo(),它定义在 Car 类中
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器