Flutter/Dart第05天:Dart特殊特性Mixin详解
摘要:在Java语言中,子类只能继承extends单个父类,实现implements多个接口(即单继承和多实现)。在Dart语言中,所有类型均是Object子类,它们也是单继承和多实现,但Dart中有个Mixin的高级特性,它可以做到更多的代码复用(单继承、多实现、多Mixin代码复用)……
Dart官网文档:https://dart.dev/language/mixins
重要说明:本博客基于Dart官网文档,但并不是简单的对官网进行翻译,在覆盖核心功能情况下,我会根据个人研发经验,加入自己的一些扩展问题和场景验证。
Mixin目的和使用方法(with)
官网文档:Mixins are a way of defining code that can be reused in multiple class hierarchies. They are intended to provide member implementations en masse.
大概意思:Mixin是一种定义可在多个类层次结构中复用代码的方法。Mixin的目标是为这些类提供一批成员实现(类属性+类方法)。
总结起来:使用Mixin可以让代码被其他类所使用(包括属性和方法)。
使用方法:通过mixin
关键字定义一个Mixin类;通过with
关键字,一个类可以同时复用多个mixin成员实现。
代码样例:如下代码,ClassA同时拥有了MixinOne+MixinTwo+MixinThree这3个Mixin的所有成员属性和类方法(感觉有的像多继承?)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| mixin MixinOne {
......
}
mixin MixinTwo {
......
}
mixin MixinThree {
......
}
class ClassA extends SupperClass with MixinOne, MixinTwo, MixinThree {
......
}
|
Mixin的使用有哪些约束呢?
- Mixin不能继承其他Mixin或者抽象类。
- Mixin不能有构造方法,也就是Mixin不能被实例化。
Mixin限定/继承其他类型(on)
为了更好的维护Mixin这些可复用的代码,我们有时需要严格限定使用Mixin的类型,通过on
关键字达到目的。
代码样例:如下代码,MixinFine通过on
关键字限定使用它的类型是SupperClass,凡是使用MixinFine的类,必须extends继承SupperClass这个Mixin限定的类型。
1
2
3
4
5
6
7
8
9
10
11
| class SupperClass {
......
}
mixin MixinFine on SupperClass {
......
}
class ClassFine extends SupperClass with MixinFine {
......
}
|
mixin class介绍和使用(类+Mixin)
我们通过mixin
定义一个Mixin,通过class
定义一个类;那么通过mixin class
就可以定义一个mixin和一个类,它们具有相同的名字和相同的类型。
Mixin和类的所有约束,在mixin class同时生效,包括如下:
- Mixin不支持extends继承其他类和with复用其他Mixin,因此mixin class也不能有extends继承其他类和with复用其他Mixin
- 普通类不支持通过on关键字限定可使用类型,因此mixin class也不支持on关键字(但是我们可以通过abstract达到此目的)。
代码样例:如下代码,mixin class
可通过with
关键字当成Mixin被使用,也可通过extends
关键字当成类被继承使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| abstract mixin class Musician {
// 含有abstract方法,使用它的类必须实现本方法
void playInstrument(String instrumentName);
void playPiano() {
playInstrument('Piano');
}
void playFlute() {
playInstrument('Flute');
}
}
class Virtuoso with Musician {
// with关键字,Musician作为一个Mixin被使用
void playInstrument(String instrumentName) {
print('Plays the $instrumentName beautifully');
}
}
class Novice extends Musician {
// extends关键字,Musician作为一个类被继承
void playInstrument(String instrumentName) {
print('Plays the $instrumentName poorly');
}
}
|
扩展问题:Mixin如何解决二义性?(覆盖)
通过上面的说明,一个类可以使用多个Mixin的实现,那么有个问题:他们是如何解决二义性的呢?
样例说明:如下代码,我们有2个Mixin,他们的属性和方法都是相同,同时使用他们时,最终的属性和方法是哪个Mixin的呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| mixin MixinA {
String className = "MixinA";
void log() {
print(className);
}
}
mixin MixinB {
String className = "MixinB";
void log() {
print(className);
}
}
class ClassMixinAB with MixinA, MixinB {
}
class ClassMixinBA with MixinB, MixinA {
}
void main() {
ClassMixinAB mixinAB = ClassMixinAB();
mixinAB.log();
// 结果:MixinB
ClassMixinBA mixinBA = ClassMixinBA();
mixinBA.log();
// 结果:MixinA
}
|
通过上面2个代码样例,基本可以判断:Mixin解决二义性的方式非常粗暴,后面Mixin覆盖前面Mixin!!!
Mixin使用场景:打印State生命周期日志
Mixin通过代码复用,可以应用在很多的应用场景。下面代码样例,可以在Flutter组件生命周期逻辑执行之后,打印响应的日志。
样例代码:LogStateMixin通过on
关键字限定/继承了State类型,内部的方法,均通过super代理了State的内容,同时打印相应的日志。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| mixin LogStateMixin<T extends StatefulWidget> on State<T> {
@override
void initState() {
super.initState();
print("====initState====");
}
@override
void dispose() {
super.dispose();
print("====dispose====");
}
// 其他方法......
}
|
在凡是想要监听组件的生命周期的组件中,可以使用上面的Mixin即可,无其他侵入代码,特别适合在Flutter应用研发过程中,通过日志观测组件的生命周期:
1
2
3
| class _MinePageState extends State<MinePage> with LogStateMixin<MinePage>
// 我的页面逻辑,无需关心日志....
}
|
这样在页面初始化、销毁的时候,打印响应的日志。
我的本博客原地址:https://ntopic.cn/p/2023093001