多态基础
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 57 课,共 110 课。
多态的意思是“多种形式”,指的是通过共同的接口处理不同类的对象的能力。当你有一个父类引用时,它可以指向任何子类对象,并根据对象的实际类型调用正确的方法。
这很强大,因为你可以编写与父类类型配合的代码,而它会自动正确处理所有子类类型:
class Animal {
void speak() => print('Some sound');
}
class Dog extends Animal {
@override
void speak() => print('Woof!');
}
class Cat extends Animal {
@override
void speak() => print('Meow!');
}
void main() {
Animal myPet = Dog(); // 父类类型,子类对象
myPet.speak(); // 输出:Woof!
myPet = Cat(); // 同一个变量,不同的对象
myPet.speak(); // 输出:Meow!
}变量 myPet 声明为 Animal,但它保存的是 Dog 或 Cat。调用 speak() 时,Dart 会在运行时查看对象的实际类型,并调用相应的重写方法。
这样你就能编写适用于任何子类的灵活函数:
void makeAllSpeak(List<Animal> animals) {
for (var animal in animals) {
animal.speak(); // 每只动物都用自己的方式叫
}
}
void main() {
var pets = [Dog(), Cat(), Dog()];
makeAllSpeak(pets);
// 输出:Woof! Meow! Woof!
}这个函数不需要了解 Dog 或 Cat,它只需处理 Animal。这样,你的代码更容易扩展,因为添加新的动物类型不需要修改现有函数。
挑战
简单让我们构建一个乐器系统,展示多态的实际应用。你将创建一个基类 Instrument 和几种乐器类型,然后编写一个函数,让任意一组乐器一起演奏,无需知道它们的具体类型。
你将把代码分成两个文件:
instruments.dart:在这里定义乐器层次结构:- 一个
Instrument类,包含一个String name属性和一个构造函数。添加一个方法play(),用于打印[name] makes a sound - 一个继承
Instrument的Guitar类,并重写play(),使其打印[name] strums melodically - 一个继承
Instrument的Drum类,并重写play(),使其打印[name] beats rhythmically - 一个继承
Instrument的Piano类,并重写play(),使其打印[name] plays harmoniously
performConcert(List<Instrument> instruments),打印Concert begins!,然后遍历列表并对每种乐器调用play(),最后打印Concert ends!- 一个
main.dart:导入乐器文件,并创建一支混合乐队来展示多态:- 创建一个类型为
List<Instrument>的列表,其中包含一把名为'Acoustic'的Guitar、一面名为'Snare'的Drum,以及一架名为'Grand'的Piano - 将这个列表传给
performConcert()
- 创建一个类型为
注意,performConcert() 使用父类型 Instrument,但每种乐器都以自己独特的方式演奏。这就是多态:同一个方法调用会根据对象的实际类型产生不同的行为。
预期输出:
Concert begins!
Acoustic strums melodically
Snare beats rhythmically
Grand plays harmoniously
Concert ends!亲手试试
import 'instruments.dart';
void main() {
// TODO: 创建一个 List<Instrument>,其中包含:
// - 一个名为 'Acoustic' 的 Guitar
// - 一个名为 'Snare' 的 Drum
// - 一个名为 'Grand' 的 Piano
// TODO: 将你的乐器列表传给 performConcert() 并调用它
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器