Mixin
Mixin 是一种代码复用技术,旨在为类添加新成员。简单地说,mixin 是可复用的代码片段。 本章节将介绍mixin基础、mixin类,以及解决mixin成员依赖问题的3种策略。
Mixin 基础
使用 mixin 关键字声明 mixin。
// ex531.dart
mixin Starter {
var started = false;
void start() => started = true;
}
在声明类时,使用关键字 with 为其添加 mixin。
// ex532.dart
import './ex531.dart';
class Game with Starter {}
class Engine with Starter {}
void main() {
var g = Game();
print(g.started); // Output: false
g.start();
print(g.started); // Output: true
}
with 子句可与 extends 子句连用,且可以为一个类添加多个mixin。
// ex533.dart
import './ex531.dart';
mixin Leveler {
int level = 0;
}
class Fun {}
class Game extends Fun with Starter, Leveler {}
void main() {
var g = Game();
g.level = 3;
g.start();
print('${g.level} ${g.started}'); // Output: 3 true
}
mixin 不能有 extends 或 with 子句,也不能声明构造函数。
Mixin 类
使用 mixin class 声明一个 mixin 类。mixin类可同时作为类和mixin使用,但也有更多的限制,实际中它的应用不多。
// ex534.dart
mixin class Player {
late String playerName;
}
mixin 类不能有 extends 或 with 或 on 子句,也不能定义生成式构造函数。
Mixin 成员依赖
有时候一个mixin需要访问一些不由它自己定义的成员(字段/方法)。换句话说,使用该mixin的类需要或显示或隐式地实现某个接口,这个接口正好包含了mixin所需的成员。下面讨论解决成员依赖的3种策略。
策略1:在mixin中定义抽象成员
// ex535.dart
mixin Adder {
set count(int value); // 1
int get count; // 1a
void add(int amount) => count += amount; // 2
}
// 3
class AddCounter with Adder {
@override
int count = 0;
}
void main() {
var c = AddCounter();
c.add(2);
assert(c.count == 2);
}
Addermixin 为属性count定义了抽象的getter和setter;Adder.add(int)方法调用了count的getter和setter;AddCounter类使用了Addermixin,且实现了count的getter和setter两个抽象方法。
策略2:让mixin实现一个接口
让 mixin 实现一个接口,使用该 mixin 的类也自然地实现了该接口。对上述 Adder mixin 进行重构,对它的两个抽象方法(即count的getter和setter),抽取至一个接口中,形成如下版本。
// ex536.dart
abstract interface class Countable {
set count(int value); // 1
int get count; // 1a
}
mixin Adder implements Countable {
void add(int amount) => count += amount; // 2
}
// 3
class AddCounter with Adder {
@override
int count = 0;
}
Countable接口定义了属性count的getter和setter;Addermixin 实现了Countable;AddCounter类使用了Addermixin,自然地实现了Countable接口。
可以向下面这样声明AddCounter类:
class AddCounter with Adder implements Countable {
// ... (omitted for brevity)
}
策略3:使用 on 子句定义超类
在声明mixin是使用on子句,用以限制mixin应用于哪些类。例如:
mixin Adder on Counter {
}
只有Counter的子孙类才可以使用 Adder mixin。同时,Adder 也可以访问 Counter 中的成员(字段/方法)。让Counter 隐式地实现 Countable 接口,形成如下新版本。
// ex537.dart
class Counter {
int count = 0; // 1
}
mixin Adder on Counter {
void add(int amount) => count += amount; // 2
}
class AddCounter extends Counter with Adder {} // 3