This page looks best with JavaScript enabled

Dart中的Mixin

 ·  ☕ 2 min read

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 实现这个功能就很合适了, 不用修改原来的方法实现, 就能实现类似在原来的代码前后插入代码一样效果.


Yang
WRITTEN BY
Yang
Developer