Dart中的Mixin

Mixin 实例 1

现在我们有类似上图的继承关系, 有 3 种能力(walk, swim, fly), 能够组合到不同的动物上. 如果我们想让 CatDuck 都拥有 walk 能力, 怎么做 ?

  1. 经典方法: 抽象一个 Walk 接口, 然后都去实现这个接口
  2. 使用mixin: 创建一个 walk mixin 类, CatDuck 都直接复用 Walk 的代码
1
2
3
4
5
6
7
8
mixin Walker {
walk() => print("walk");
}

// 或者: 没有构造函数的类也支持 mixin
class Walker {
walk() => print("walk");
}
  1. 使用接口实现
1
2
3
4
5
6
7
class Duck extends Mammal implements Walker {

@override
walk() {
// 需要自己再实现
}
}
  1. 使用 mixin
1
2
3
4
5
class Duck extends Mammal with Flyer, Walker {}

// 使用时, 直接就能复用 Walker 的代码
final duck = Duck();
duck.walk();

不同点

  • 使用 mixin 可以向类A 添加 类B 的代码, 且 A 不用继承自 B, 也不用单独实现 B 的方法
  • extends不同: 继承只能继承一个类, 而 mixin 可以复用多个类
  • implements不同: 实现需要单独实现接口的功能, 而 mixin 可以直接使用
  • mixin 多个类时, 如果存在相同的方法和属性, 会使用最后 with 的类的方法和属性

Minxin: 实例 2

不修改源代码的情况下, 为方法添加日志

1
2
3
abstract class Mammal extends Animal {
eat() => print("eat");
}
1
2
3
4
5
6
7
8
9
10
// 定义一个 mixin, 声明作用于 Mammal 上
mixin EatLog on Mammal {
@override
eat() {
// 在原方法前后添加日志
print("start eat");
super.eat();
print("end eat");
}
}
1
2
3
4
5
6
7
8
9
class Cat extends Mammal with Walker, EatLog {}

main() {
final cat = Cat();
cat.eat();
// start eat
// eat
// end eat
}

使用 Mixin 实现这个功能就很合适了, 不用修改原来的方法实现, 就能实现类似在原来的代码前后插入代码一样效果.