Menu
CoddyTech

实现与继承

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

现在你已经了解了 extends 和 implements,接下来我们来说明何时使用它们。

如果你想继承行为,就使用 extends。你的子类可以直接使用父类的所有代码,还能在此基础上进行扩展:

class Animal {
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  void bark() {
    print('Woof!');
  }
}

void main() {
  var dog = Dog();
  dog.breathe();  // 继承而来,可直接使用
  dog.bark();
}

如果你想在不继承代码的情况下确保结构符合要求,请使用 implements。你必须自己编写每个方法:

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');  // 完全自定义的实现
  }
}

关键区别在于:extends表示“我是这一类型”,而implements表示“我能做它能做的事”。Dog是一种Animal,呼吸方式也相同。Robot不是动物,但它可以用自己的逻辑满足同一份契约。

记住:你只能继承一个类,但可以实现多个接口。对于真正的继承关系,选择 extends;当你需要灵活性,或想在不共享实现细节的情况下强制遵守契约时,选择 implements。

challenge icon

挑战

简单

我们来构建一个工作者系统,演示何时使用 extends,何时使用 implements。你将创建一个基础工作者类,然后展示这两种方式:一个类真正“是”工作者,并继承行为;另一个类只是“能做”工作者能做的事,但使用完全自定义的逻辑。

你将把代码组织到两个文件中:

  • worker.dart:在这里定义工作者层级结构:
    • 创建一个 Worker 类,其中包含 String name 属性和构造函数。添加一个方法 work(),用于输出 [name] is working...;再添加一个方法 takeBreak(),用于输出 [name] takes a coffee break
    • 创建一个 OfficeWorker 类,使其 extends Worker。添加一个 String department 属性。重写 work(),使其输出 [name] is typing reports in [department],但保留继承而来的 takeBreak() 行为
    • 创建一个 RobotWorker 类,使其 implements Worker。添加一个 String model 属性。由于机器人并不是真正的工作者,但能做工作者能做的事,因此要提供完全自定义的实现:work() 应输出 Robot [model] is assembling parts,而 takeBreak() 应输出 Robot [model] is recharging
  • main.dart:导入工作者文件,并展示这两种方式:
    • 创建一个名为 'Alice'、属于 'Marketing' 部门的 OfficeWorker
    • 创建一个型号为 'RX-7' 的 RobotWorker
    • 对于办公室工作者,先调用 work(),再调用 takeBreak()
    • 输出一个空行
    • 对于机器人工作者,先调用 work(),再调用 takeBreak()

注意,OfficeWorker 会自动继承 takeBreak(),因为它通过 extends 继承了 Worker,它确实“是”一个工作者。与此同时,RobotWorker 必须为所有内容提供自己的实现,因为它只是实现了接口。它“能做”工作者能做的事,但方式是它自己的机器人风格。

预期输出:

Alice is typing reports in Marketing
Alice takes a coffee break

Robot RX-7 is assembling parts
Robot RX-7 is recharging

亲手试试

import 'worker.dart';

void main() {
  // TODO: 创建一个名为 'Alice'、属于 'Marketing' 部门的 OfficeWorker
  
  // TODO: 创建一个型号为 'RX-7' 的 RobotWorker
  
  // TODO: 对办公室员工,先调用 work(),再调用 takeBreak()
  
  // TODO: 打印一个空行
  
  // TODO: 对机器人员工,先调用 work(),再调用 takeBreak()
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器