Menu
CoddyTech

创建混入

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

现在你已经了解了混入是什么,接下来看看如何正确创建它们。声明混入时要使用 mixin 关键字,而不是 class。

mixin Logging {
  void log(String message) {
    print('[LOG] $message');
  }
  
  void logError(String error) {
    print('[ERROR] $error');
  }
}

混入可以包含方法、属性,甚至获取器和设置器,就像类一样。不过,有一条重要规则:混入不能有构造函数。混入的目的是被“混入”到其他类中,而不是直接实例化,因此不需要初始化逻辑。

mixin Timestamped {
  DateTime createdAt = DateTime.now();
  
  String get formattedTime => createdAt.toString();
  
  void printTimestamp() {
    print('Created at: $formattedTime');
  }
}

class Document with Timestamped {
  String title;
  Document(this.title);
}

void main() {
  var doc = Document('Report');
  doc.printTimestamp();  // 使用 mixin 的方法
  print(doc.createdAt);  // 使用 mixin 的属性
}

使用 with 应用混入时,它的所有成员都会成为你的类的一部分。这个类可以直接使用这些成员,任何拥有该类实例的代码也可以使用它们。这样,混入就成了一种简洁的方式,可以添加可重复使用的功能,而不必处理复杂的继承层次结构。

challenge icon

挑战

简单

让我们构建一个消息系统,展示如何创建包含方法、属性和 getter 的 mixin。你将设计一个 mixin,为不同类型的消息添加格式化功能。

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

  • messaging.dart:在这里定义 mixin 和消息类:
    • 一个 Formattable mixin,其中包含:
      • 一个初始值为 '>>>' 的 String prefix 属性
      • 一个返回 ' | ' 的 getter separator
      • 一个方法 format(String text),返回字符串 [prefix][separator][text]
      • 一个方法 formatBold(String text),返回 **[text]**
    • 一个使用 Formattable mixin 的 TextMessage 类。添加一个带有构造函数的 String sender 属性。再添加一个方法 send(String content),打印使用 [sender]: [content] 调用 format() 的结果。
    • 一个同样使用 Formattable mixin 的 AlertMessage 类。添加一个带有构造函数的 String level 属性。再添加一个方法 alert(String content),打印使用 [[level]] [formatBold(content)] 调用 format() 的结果。
  • main.dart:导入消息文件,并演示这两种消息类型如何通过 mixin 获得格式化功能:
    • 创建一个发送者为 'Alice' 的 TextMessage
    • 创建一个级别为 'WARNING' 的 AlertMessage
    • 在文本消息上调用 send('Hello there!')
    • 在警报消息上调用 alert('System overload')

你的 mixin 展示了 mixin 可以包含具有默认值的属性、用于计算值的 getter,以及多个甚至可以相互调用的方法。只需使用 with 关键字,这两个消息类就能获得所有这些功能。

预期输出:

>>> | Alice: Hello there!
>>> | [WARNING] **System overload**

亲手试试

import 'messaging.dart';

void main() {
  // TODO:创建一个发送者为 'Alice' 的 TextMessage
  
  // TODO:创建一个级别为 'WARNING' 的 AlertMessage
  
  // TODO:在文本消息上调用 send('Hello there!')
  
  // TODO:在警报消息上调用 alert('System overload')
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器