前言
mixins一直是我一个比较困惑的关键字,虽然已经做了flutter几个月了,但是并没有去搞懂mixins是什么功能,最佳刚好看了些文章,这里做个终结。
为什么需要mixins
这里我们有一个Animal的超类,它有三个子类型Mammal, Bird和Fish, 最底下我们有具体的类,类左边的小方块代表一些行为,例如,蓝色的小方块代表swim行为.
一些动物有相同的行为,例如cat和dove都可以walk, 但是cat不能飞。
这些行为分布不均匀,不能在超类里面实现。当然你可以想到的是我再抽象一些Walker,Swimmer,Flyer这些类,但是在Dart中只能支持单继承.
既然不能使用继承,那我只好每个类都写一遍它的实现咯?不过Dart提供了更方便的方式就是使用mixins
对于mixins的定义是:
mixins是重用一块类代码在多个类层级中
如何使用mixins
首先我们创建一个mixins, 它和创建普通类的方式一样
class Walker {
void walk() {
print("I'm walking");
}
}
为了防止mixin被初始化或者继承,我们可以定义为abstract class
abstract class Walker {
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory Walker._() => null;
void walk() {
print("I'm walking");
}
}
去使用mixin,使用with关键字,后面跟上mixin名字
class Cat extends Mammal with Walker {}
class Dove extends Bird with Walker, Flyer {}
定义Walker mixin在Cat类上,这得Cat可以调用walk()方法。
main(List<String> arguments) {
Cat cat = Cat();
Dove dove = Dove();
// 一只cat可以walk.
cat.walk();
// 一只dove可以walk和fly.
dove.walk();
dove.fly();
// 一只cat不可以调用fly.
// cat.fly();
}
mixins的继承关系
猜猜下面的代码是什么输出
class A {
String getMessage() => 'A';
}
class B {
String getMessage() => 'B';
}
class P {
String getMessage() => 'P';
}
class AB extends P with A, B {}
class BA extends P with B, A {}
void main() {
String result = '';
AB ab = AB();
result += ab.getMessage();
BA ba = BA();
result += ba.getMessage();
print(result);
}
AB和BA类都继承来自P,但是mixin A和B的顺序不同, 3个类A,B, P都有一个getMessage方法。
首先我们调用AB实例化对象的的getMessage,然后调用BA类实例化对象的的getMessage。所以最终的结果是什么呢?
最终它会输出BA.
要了解为什么,我们需要搞懂mixins的继承顺序. 它是线性化的,它的继承关系如下
所以它是一种线性的继承顺序,从左到右。
mixins的类型
首先我们来看看下面程序的输出
class A {
String getMessage() => 'A';
}
class B {
String getMessage() => 'B';
}
class P {
String getMessage() => 'P';
}
class AB extends P with A, B {}
class BA extends P with B, A {}
void main() {
AB ab = AB();
print(ab is P);
print(ab is A);
print(ab is B);
BA ba = BA();
print(ba is P);
print(ba is A);
print(ba is B);
}
所有的print都会打印true。这意味着,由mixin声明的类,不光是超类的子类,也是mixin的子类.
关键字on
另外dart还提供一个on关键字用于限制mixin的使用范围。
例如:
abstract class Super {
void method() {
print("Super");
}
}
class MySuper implements Super {
void method() {
print("MySuper");
}
}
mixin Mixin on Super {
void method() {
super.method();
print("Sub");
}
}
class Client extends MySuper with Mixin {}
void main() {
Client().method();
}
在示例代码中Mixin的使用实际限制在必须继承Super的类,因为Mixin用on关键字限制了它的作用域是Super的子类.
什么时候使用mixins?
当需要实现某个共享功能在类里,但是不想破坏原有的类层级结构的时候可以使用mixins进行类的抽象。就拿之前Animal案例来说,walk实际上是一个可以在各个类中共享的功能,但是我不想在超类里去实现,这样会破坏类层级结构,就可以使用mixins这种方式了.