在 Dart 语言中,我们经常可以看到对 mixin 关键字的使用,根据字面理解,就是混合的意思。
1.extends + implements
abstract class First {
void doPrint() {
print('First');
}
}
abstract class Second {
void doPrint() {
print('Second');
}
}
class Father {
void doPrint() {
print('Father');
}
}
class Son1 extends Father implements First,Second {
}
调用:
Son1 son = Son1();
son.doPrint();
打印:
Father
implements 的abstract 需要实现接口方法,但是extends 具备同名方法,所以无需重写
如果Second或者First中再加入一个方法
abstract class Second {
void doPrint() {
print('Second');
}
void test(){
print('test');
}
}
就会报错
Error: The non-abstract class 'Son1' is missing implementations for these members:
- Second.test
Try to either
- provide an implementation,
- inherit an implementation from a superclass or mixin,
- mark the class as abstract, or
- provide a 'noSuchMethod' implementation.
提示Son1中需要实现test()方法,说明implements关键字只是声明要实现接口方法,abstract相当于interface,而doPrint()方法具体实现是在extend继承的Father中实现了,所以接口声明的方法要在Son中或者Father中实现。
2.extends + with
abstract class First {
void doPrint() {
print('First');
}
}
abstract class Second {
void doPrint() {
print('Second');
}
}
class Father {
void doPrint() {
print('Father');
}
}
class Son1 extends Father with First,Second {
}
调用:
Son1 son = Son1();
son.doPrint();
打印:
Second
with关键字能够实现mixin,可以想象成多继承,而且是以类似于栈的形式实现(最后一个混入的 mixins 会覆盖前面一个 mixins 的特性,所以with 后面的顺序是需要注意的),同一方法调用最外边的Second
with和implements的区别就是不需要实现继承接口方法
3.extends + with + implements
abstract class First {
void doPrint() {
print('First');
}
}
abstract class Second {
void doPrint() {
print('Second');
}
}
class Father {
void doPrint() {
print('Father');
}
}
class Son1 extends Father with First implements Second {
}
调用:
Son1 son = Son1();
son.doPrint();
打印:
First
说明Second是接口,with关键字依旧遵守上边例子中的性质,首先实现First中的方法(with 相当于实现了可以省略不写,但是同名,也相当于重写了implements的接口),如果把First中的doPrint()方法注释掉,打印Father
4.mixin关键字的使用
一般情况下,mixin与on关键字结合使用,相当于限定了父类,组合的时候需要一致,如果不与on关键字一起使用,作用类似于abstract。所以着重看下与on关键字配合的例子
class Father {
void init() {
print('Father init');
}
}
//当使用on关键字,则表示该mixin只能在那个类的子类使用了,
// 那么结果显然的,mixin中可以调用那个类定义的方法、属性
mixin FirstMixin on Father {
void init() {
print('FirstMixin init start');
super.init();
print('FirstMixin init end');
}
}
mixin SecondMixin on Father {
void init() {
print('SecondMixin init start');
super.init();
print('SecondMixin init end');
}
}
class Son2 extends Father with FirstMixin, SecondMixin {
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
调用:
Son2().init();
打印:
flutter: Son2 init start
flutter: SecondMixin init start
flutter: FirstMixin init start
flutter: Father init
flutter: FirstMixin init end
flutter: SecondMixin init end
flutter: Son2 init end
与例子2一样,但是,这里super调用会发现,with关键字把FirstMixin和SecondMixin以及Father自动关联为父子,这一切都是基于on关键字,且对Father这个家族(可以理解为整个家族)增加束缚,Son2这个类也只能继承Father,如果增加其他家族的mixin,就会报错。
如:
class OtherFamily{
void init(){
print('其他家族');
}
}
mixin OtherFamilyMixin on OtherFamily{
@override
void init() {
// TODO: implement init
super.init();
}
}
class Son2 extends Father with FirstMixin, SecondMixin ,OtherFamilyMixin{
@override
void init() {
// TODO: implement init
super.init();
}
}
报错:
Error: '_Son2&Father&FirstMixin&SecondMixin' doesn't implement 'OtherFamily' so it can't be used with 'OtherFamilyMixin'.
- 'Father with FirstMixin, SecondMixin' is from 'package:github_app/common/page/HomePage.dart' ('lib/common/page/HomePage.dart').
- 'OtherFamily' is from 'package:github_app/common/page/HomePage.dart' ('lib/common/page/HomePage.dart').
- 'OtherFamilyMixin' is from 'package:github_app/common/page/HomePage.dart' ('lib/common/page/HomePage.dart').
class Son2 extends Father with FirstMixin, SecondMixin ,OtherFamilyMixin{
mixin OtherFamilyMixin on OtherFamily,on限定的父类组别和其他的mixin不一样,所以报错。如果把OtherFamilyMixin改成OtherFamily,即非mixin,这个时候就是with最后一个覆盖了前面的组别。那么Son也改换门庭了,只会打印OtherFamily的实现。
class OtherFamily{
void init(){
print('其他家族');
}
}
mixin OtherFamilyMixin on OtherFamily{
@override
void init() {
// TODO: implement init
super.init();
}
}
class Son2 extends Father with FirstMixin, SecondMixin ,OtherFamily{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
打印:
flutter: Son2 init start
flutter: 其他家族
flutter: Son2 init end
看看,连他爸爸都不要了,super直接指向OtherFamily,但是他又不忘记继承的Father,还是依旧能调用Father里的方法,比如在Father里加入eat方法
class Father {
void init() {
print('Father init');
}
void eat(){
print('eat food');
}
}
调用:
Son2().init();
Son2().eat();
打印:
flutter: Son2 init start
flutter: 其他家族
flutter: Son2 init end
flutter: eat food
真的是脚踏两只船,就像段誉,血脉上是段延庆,可以用段延庆的血脉,然后武功上用着段正淳的一阳指,好乱啊。
5.on关键字
on关键字后边不止可以跟一个类,再加一个类会出现什么情况
class Father{
void init() {
print('Father init');
}
}
abstract class Mother{
void initMother();
}
//当使用on关键字,则表示该mixin只能在那个类的子类使用了,
// 那么结果显然的,mixin中可以调用那个类定义的方法、属性
mixin FirstMixin on Father {
void init() {
print('FirstMixin init start');
super.init();
print('FirstMixin init end');
}
}
mixin SecondMixin on Father,Mother {
void init() {
print('SecondMixin init start');
super.init();
print('SecondMixin init end');
}
}
class Son2 extends Father with FirstMixin, SecondMixin{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
跑项目执行报错,因为mixin的on限定不是一个类,即不能一个组别
打印:
Error: The non-abstract class 'Son2' is missing implementations for these members:
- Mother.initMother
Try to either
Error: '_Son2&Father&FirstMixin' doesn't implement 'Mother' so it can't be used with 'SecondMixin'.
说是需要实现initMother方法,好吧我们在Son2中实现该方法
class Son2 extends Father with FirstMixin, SecondMixin{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
@override
void initMother() {
// TODO: implement initMother
}
}
打印:
Error: '_Son2&Father&FirstMixin' doesn't implement 'Mother' so it can't be used with 'SecondMixin'.
好吧,我们继续实现,在FirstMixin中实现
//当使用on关键字,则表示该mixin只能在那个类的子类使用了,
// 那么结果显然的,mixin中可以调用那个类定义的方法、属性
mixin FirstMixin on Father implements Mother{
void init() {
print('FirstMixin init start');
super.init();
print('FirstMixin init end');
}
@override
void initMother() {
// TODO: implement initMother
}
}
成功了!!
然后我又把Sons中的initMother实现注释掉,还是可以成功!然后把FirstMixin中的实现去掉,只在Father中实现initMother
class Father implements Mother{
void init() {
print('Father init');
}
@override
void initMother() {
// TODO: implement initMother
}
}
class Mother{
void initMother(){
}
}
//当使用on关键字,则表示该mixin只能在那个类的子类使用了,
// 那么结果显然的,mixin中可以调用那个类定义的方法、属性
mixin FirstMixin on Father{
void init() {
print('FirstMixin init start');
super.init();
print('FirstMixin init end');
}
}
mixin SecondMixin on Father,Mother {
void init() {
print('SecondMixin init start');
super.init();
print('SecondMixin init end');
}
}
class Son2 extends Father with FirstMixin, SecondMixin{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
还是可以成功!!
这时,有个大胆的想法,是不是遵循例子2,with关键字依次往前推,只要某个mixin实现Mother就行?
SecondMixin->FirstMixin->Father
然后把on Father,Mother的mixin放到倒数第二个,在倒数第一个实现
class Father{
void init() {
print('Father init');
}
}
class Mother{
void initMother(){
}
}
//当使用on关键字,则表示该mixin只能在那个类的子类使用了,
// 那么结果显然的,mixin中可以调用那个类定义的方法、属性
mixin FirstMixin on Father{
void init() {
print('FirstMixin init start');
super.init();
print('FirstMixin init end');
}
}
mixin SecondMixin on Father,Mother {
void init() {
print('SecondMixin init start');
super.init();
print('SecondMixin init end');
}
}
class Son2 extends Father with SecondMixin,FirstMixin{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
打印:
Error: The non-abstract class 'Son2' is missing implementations for these members:
- Mother.initMother
Try to either
Error: 'Father' doesn't implement 'Mother' so it can't be used with 'SecondMixin'.
失败!!
注意看,第二个Error由之前的 '_Son2&Father&FirstMixin'变成了具体的Father,说明是往前推得。
既然这样,再来验证一下,我们添加一个ThirdMixin,把on Mother,Father的SecondMixin放在中间
mixin ThirdMixin on Father {
void init() {
print('ThirdMixin init start');
super.init();
print('ThirdMixin init end');
}
}
class Son2 extends Father with ThirdMixin,SecondMixin,FirstMixin{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
打印:
Error: The non-abstract class 'Son2' is missing implementations for these members:
- Mother.initMother
Error: '_Son2&Father&ThirdMixin' doesn't implement 'Mother' so it can't be used with 'SecondMixin'.
果然不出所料!打印又成了_Son2&Father&ThirdMixin
FirstMixin找SecondMixin是可以找到同一组别的,SecondMixin找ThirdMixin,却发现ThirdMixin的on只限定了一个。
既然这样,也不能在Father中实现啊!
我们就把Mother放到Son中的with后边,而且要放到SecondMixin的前边
class Son2 extends Father with Mother,ThirdMixin,SecondMixin,FirstMixin{
@override
void init() {
print('Son2 init start');
super.init();
print('Son2 init end');
}
}
这样就OK了(往前找同类别,father是满足的),可以试验一下把Mother放SecondMixin后边,又会报错,这样体现了mixin的约束性,强制Son必须继承Mother这个类。