抽象类
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 43 课,共 110 课。
抽象类是不能直接实例化的类。它为其他类提供蓝图,定义子类必须遵循的通用结构。你可以使用 abstract 关键字创建抽象类。
abstract class Shape {
String color;
Shape(this.color);
void describe() {
print('A $color shape');
}
}
class Circle extends Shape {
double radius;
Circle(String color, this.radius) : super(color);
}
void main() {
// Shape s = Shape('red'); // 错误!不能实例化抽象类
var circle = Circle('blue', 5.0);
circle.describe(); // 一个蓝色的形状
}当某个概念过于宽泛,无法独立存在时,抽象类就很有用。“形状”是一个概念,但如果不知道它是圆形、矩形还是三角形,你就无法画出这个形状。抽象类定义了所有形状的共同点,而具体子类则提供具体细节。
请注意,抽象类仍然可以包含已实现的普通方法(如 describe())和构造函数。子类会像普通继承一样继承这些内容。关键区别只是你不能直接创建抽象类本身的实例,必须使用具体子类。
挑战
简单让我们构建一个车辆系统,演示抽象类如何作为更具体类型的蓝图。你将创建一个抽象基类,定义所有车辆的共同属性,然后通过扩展它来创建具体的车辆类型。
你将把代码整理到两个文件中:
vehicle.dart:在这里定义车辆的类层次结构:- 一个
abstract class Vehicle,带有String brand和int year属性。添加一个接收这两个值的构造函数,以及一个会打印[brand] ([year])的方法displayInfo() - 一个扩展
Vehicle的Car类,并添加int doors属性。添加一个会打印Beep beep!的方法honk() - 一个扩展
Vehicle的Motorcycle类,并添加bool hasSidecar属性。添加一个会打印Vroom!的方法revEngine()
- 一个
main.dart:导入车辆文件,并演示抽象类的工作方式:- 创建一辆品牌为
'Toyota'、年份为2022、车门数为4的Car - 调用它从 Vehicle 继承的
displayInfo()方法 - 打印
Doors: [doors] - 调用它的
honk()方法 - 打印一个空行
- 创建一辆品牌为
'Harley'、年份为2021、hasSidecar 为false的Motorcycle - 调用它的
displayInfo()方法 - 打印
Has sidecar: [hasSidecar] - 调用它的
revEngine()方法
- 创建一辆品牌为
请记住,由于 Vehicle 是抽象类,你不能直接创建它的实例,必须使用具体子类。Car 和 Motorcycle 都会从抽象父类继承 displayInfo() 方法。
预期输出:
Toyota (2022)
Doors: 4
Beep beep!
Harley (2021)
Has sidecar: false
Vroom!亲手试试
import 'vehicle.dart';
void main() {
// TODO: 创建一个 Car,品牌为 'Toyota',年份为 2022,doors 为 4。
// TODO: 对这辆车调用 displayInfo()。
// TODO: 打印 "Doors: [doors]"。
// TODO: 对这辆车调用 honk()。
// TODO: 打印一个空行。
// TODO: 创建一个 Motorcycle,品牌为 'Harley',年份为 2021,hasSidecar 为 false。
// TODO: 对这辆摩托车调用 displayInfo()。
// TODO: 打印 "Has sidecar: [hasSidecar]"。
// TODO: 对这辆摩托车调用 revEngine()。
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器