flutter mixin

在 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这个类。

你可能感兴趣的:(flutter mixin)