Menu
CoddyTech

混入中的 on 关键字

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

有时,混入需要使用被混入的类中的方法或属性。on 关键字可以限制混入,使其只能与扩展特定类型的类一起使用。

class Animal {
  String name;
  Animal(this.name);
  
  void breathe() => print('$name is breathing');
}

mixin Swimming on Animal {
  void swim() {
    print('$name is swimming');  // 可以访问 Animal 中的 'name'
    breathe();  // 可以调用 Animal 的方法
  }
}

class Fish extends Animal with Swimming {
  Fish(String name) : super(name);
}

on Animal 声明表示,这个混入只能应用于继承 Animal 的类。这样可以确保混入能够访问 Animal 的成员。如果没有 on,混入就不知道 name 或 breathe() 是否存在。

如果你尝试在不兼容的类上使用受限混入,Dart 会给出编译时错误:

class Robot with Swimming {}  // 错误!Robot 没有继承 Animal

当你的混入功能依赖基类提供的特定能力时,这种约束很有用。它能建立更安全的契约:混入会承诺提供某些行为,但只有在具备正确运行所需的基础条件时才会这样做。

challenge icon

挑战

简单

我们来构建一个车辆系统,演示 on 关键字如何限制混入只能用于特定的基类。你将创建一个添加涡轮增压功能的混入,但它只能由扩展 Vehicle 基类的类使用。

你将把代码分成两个文件:

  • vehicles.dart:在这里定义基类、受限混入和车辆类型:
    • 定义一个 Vehicle 类,其中包含 String model 属性和 int speed 属性。添加一个接收这两个值的构造函数。再添加一个方法 accelerate(),用于打印 [model] accelerating to [speed] km/h
    • 定义一个使用 on 关键字限制为只能用于 Vehicle 的 TurboBoost 混入。这个混入应包含一个方法 activateTurbo(),用于打印 [model] TURBO ACTIVATED!,然后调用 accelerate()(由于 on Vehicle 约束,这两者都可以访问)
    • 定义一个扩展 Vehicle 并使用 TurboBoost 混入的 SportsCar 类。添加一个 String color 属性。构造函数应接收 model、speed 和 color。再添加一个方法 showOff(),用于打印 [color] [model] ready to race!
  • main.dart:导入车辆文件,并演示受限混入的工作方式:
    • 创建一辆 SportsCar,其 model 为 'Ferrari',speed 为 320,color 为 'Red'
    • 调用 showOff()
    • 调用 activateTurbo()

TurboBoost 混入可以访问 model 并调用 accelerate(),因为 on Vehicle 声明确保它只会混入扩展 Vehicle 的类中。这样就建立了一个安全的约定,让混入明确知道有哪些功能可用。

预期输出:

Red Ferrari ready to race!
Ferrari TURBO ACTIVATED!
Ferrari accelerating to 320 km/h

亲手试试

import 'vehicles.dart';

void main() {
  // TODO: 创建一个 SportsCar,model 为 'Ferrari',speed 为 320,color 为 'Red'。
  
  // TODO: 调用 showOff()。
  
  // TODO: 调用 activateTurbo()。
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器