Menu
CoddyTech

通过接口实现多态

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 58 课,共 110 课。

在上一课中,你通过继承了解了多态,也就是使用父类类型来处理子类对象。不过,多态也可以通过接口实现,而且这种方式通常更灵活。

当类实现相同的接口时,即使它们之间没有继承关系,你也可以将它们视为多态对象:

abstract class Printable {
  void printDetails();
}

class Invoice implements Printable {
  @override
  void printDetails() => print('Invoice #1234');
}

class Report implements Printable {
  @override
  void printDetails() => print('Monthly Report');
}

class Receipt implements Printable {
  @override
  void printDetails() => print('Receipt for purchase');
}

void printAll(List<Printable> items) {
  for (var item in items) {
    item.printDetails();
  }
}

void main() {
  var documents = [Invoice(), Report(), Receipt()];
  printAll(documents);
}

Invoice、Report 和 Receipt 是完全无关的类,它们没有共同的父类。不过,由于它们都实现了 Printable,我们可以将它们存储在同一个列表中,并对每个对象调用 printDetails()。

这很强大,因为它让你可以定义行为契约,而不必强制使用继承层次结构。任何类都可以实现接口,无论它继承自什么。这样一来,你的代码会更模块化,因为你可以添加新的可打印类型,而无需修改现有代码,只需实现接口即可。

challenge icon

挑战

简单

让我们构建一个媒体播放器系统,通过接口展示多态。你将创建一个接口来定义“可播放”的含义,然后实现几种互不相关的媒体类型,让它们都遵循这个约定。这样一来,即使它们之间没有继承关系,也能用统一的方式处理。

你将把代码整理到两个文件中:

  • media.dart:在这里定义接口和媒体类:
    • 创建一个抽象类 Playable,其中包含两个抽象方法:play() 和 String getMediaType()
    • 创建一个实现 Playable 的 Song 类。它应包含一个 String title 和一个 String artist。它的 play() 方法会输出 Playing song: [title] by [artist],而 getMediaType() 返回 'Audio'
    • 创建一个实现 Playable 的 Video 类。它应包含一个 String title 和一个 int duration(分钟)。它的 play() 方法会输出 Playing video: [title] ([duration] min),而 getMediaType() 返回 'Video'
    • 创建一个实现 Playable 的 Podcast 类。它应包含一个 String title 和一个 int episode。它的 play() 方法会输出 Playing podcast: [title] - Episode [episode],而 getMediaType() 返回 'Podcast'
    另外,创建一个函数 playAll(List<Playable> playlist),遍历列表,并为每个项目输出 [Media Type]:,然后调用该项目的 play()。
  • main.dart:导入媒体文件,并演示基于接口的多态:
    • 创建一个 List<Playable>,其中包含一个标题为 'Imagine'、艺术家为 'John Lennon' 的 Song,一个标题为 'Dart Tutorial'、时长为 15 的 Video,以及一个标题为 'Tech Talk'、集数为 42 的 Podcast
    • 将这个列表传递给 playAll()

注意,Song、Video 和 Podcast 没有共同的父类,它们是完全互不相关的类型。但因为它们都实现了 Playable,你可以将它们存储在同一个列表中,并通过接口统一处理。

预期输出:

Audio:
Playing song: Imagine by John Lennon
Video:
Playing video: Dart Tutorial (15 min)
Podcast:
Playing podcast: Tech Talk - Episode 42

亲手试试

import 'media.dart';

void main() {
  // TODO: 创建一个 List<Playable>,包含:
  // - 一个 Song,title 为 'Imagine',artist 为 'John Lennon'
  // - 一个 Video,title 为 'Dart Tutorial',duration 为 15
  // - 一个 Podcast,title 为 'Tech Talk',episode 为 42
  
  // TODO: 将列表传给 playAll()
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器