Mixin 实例 1
现在我们有类似上图的继承关系, 有 3 种能力(walk, swim, fly), 能够组合到不同的动物上. 如果我们想让 Cat
和 Duck
都拥有 walk
能力, 怎么做 ?
- 经典方法: 抽象一个
Walk
接口, 然后都去实现这个接口
- 使用mixin: 创建一个 walk mixin 类,
Cat
和 Duck
都直接复用 Walk
的代码
1
2
3
4
5
6
7
8
|
mixin Walker {
walk() => print("walk");
}
// 或者: 没有构造函数的类也支持 mixin
class Walker {
walk() => print("walk");
}
|
- 使用接口实现
1
2
3
4
5
6
7
|
class Duck extends Mammal implements Walker {
@override
walk() {
// 需要自己再实现
}
}
|
- 使用 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 实现这个功能就很合适了, 不用修改原来的方法实现, 就能实现类似在原来的代码前后插入代码一样效果.