2020-11-08

什么是Mixin

从翻译角度看mixin是混入的意思,从技术的角度mixin是一个没有构造函数的类。
iOS的理解mixin类似于 swift中protocol允许 默认实现。如下:

protocol Fly {
    //协议中定义 为提供默认实现
    func flyLow()
}
extension Fly {
    //对协议进行扩展 提供默认实现
   func fly(){
        print("fly")
    }
}

class Bird : Fly {
    //未提供默认实现的类需要实现接口
    func flyLow() {
        print("fly low")
    }
    //默认实现的类可以选择不在实现
//    func fly() {
//
//    }
    
}

let bird = Bird()
bird.fly()
bird.flyLow()
--------------------------------------------------
fly
fly low

在Android 可以理解为带默认实现的 interface

    interface Fly{
        public default void fly(){
            System.out.println("fly");
        }
    }

举个例子

我们用经典的Animals举个例子,直接看代码,
这里我们定义了一个抽象类 animal,添加了三种行为,跑步,飞,游泳。
创造了三个小动物,小鸟、小狗、青蛙,都继承与Animal,分别实现了飞、跑,跑和游泳。让我们看看现在的代码群在什么问题?

abstract class Animal {}

class Run {
  run() {
    print('run');
  }
}

class Fly {
  fly() {
    print('fly');
  }
}

class Swim {
  swim() {
    print('swim');
  }
}

class Bird extends Animal implements Fly {
  fly() {
    print('bird fly');
  }
}

class Dog extends Animal implements Run {
  //这样写时报错的
  @override
  run() {
    // super.run();
  }
}

class Frog extends Animal implements Run, Swim {
  run() {
    print("run");
  }

  swim() {
    print('swim');
  } 
}

main(List<String> args) {
  Frog frog = Frog();
  frog.run();
  frog.swim();
}

注:为什么行为类可以直接当做接口实现,是因为dart类创建的时候就添加了一个隐式接口类,可用来实现用。
目前的表象
第一、小动物类中,复写了行为类方法后,不能使用super调用,因为默认super找的是animal中的方法。
第二、如果要实现就需要在小动物类中将需要实现的方法全部重新实现。
这样对比swift、java当中协议的、接口的默认实现,就略显不灵活了,尤其在多个类层次结构中重用类的代码的方法时候就很麻烦了。dart使用了另外一种方式解决这个问题,那就是mixin。让我们对上述代码进行改造下。

abstract class Animal {}

mixin Run {
  run() {
    print('run');
  }
}

mixin Fly {
  fly() {
    print('fly');
  }
}
//mixin使用 class也是可以的
class Swim {
  swim() {
    print('swim');
  }
}

class Bird extends Animal with Fly {}

class Dog extends Animal with Run {}

class Frog extends Animal with Swim, Run {}

main(List<String> args) {
  Bird bird = Bird();
  bird.fly();

  Dog dog = Dog();
  dog.run();

  Frog frog = Frog();
  frog.run();
  frog.swim();
}

注:如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class。
这样改造后小动物们不用在重新复写行为方法,直接调用即可。

多继承

dart中多继承有两种方式:
第一种 implement 多个接口类,但是必须要实现类中所有方法与变量。
第二种,就是使用上边的mixin。

特性

mixin有一个特性,那就是线性化,上边的例子中如果每个行为的函数都一样,类似于下边这种:

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);
}

这个会输出什么结果呢,会输出如下结果
BA
大家可能想会想到,这个跟mixin的顺序有关系,最后混入的 mixin 的函数,被调用了。这说明最后一个混入的 mixins 会覆盖前面一个 mixins 的特性。
这里引出一个概念线性化,声明 mixin 的顺序代表了继承链的继承顺序,声明在后面的 mixin,一般会最先执行。
实际上这段代码

class AB extends P with A, B {}

class BA extends P with B, A {}

在语义上等同于

class PA extends P with A;
class PAB extends PA with B;

class AB extends PAB {}

class PB extends P with B;
class PBA extends PB with A;

class BA extends PBA {}

最终的继承关系如下图
在这里插入图片描述
可有看出了这是一个线性的继承关系,dart在P与AB、BA中创建了中间类来做方法混入,这就能解释了为什么调用的时候都是顺序加入最后的一个了。

mixin的使用场景

至此,大家一起探讨一下,根据这个mixin的特性,在工程中那些方面可以使用?

这是一个 SQL 语句,用于向借阅表中插入数据。该表包含以下字段:借阅编号、读者编号、书籍编号、借阅日期、归还日期、借阅状态。每条数据表示一次借阅记录。其中借阅编号、读者编号、书籍编号、借阅日期和借阅状态是必填项,归还日期为可选项,如果借阅状态为“已还”则必须填写归还日期。 具体插入的数据如下: - 借阅编号:100001,读者编号:123413,书籍编号:0001,借阅日期:2020-11-05,归还日期:NULL,借阅状态:借阅 - 借阅编号:100002,读者编号:223411,书籍编号:0002,借阅日期:2020-9-28,归还日期:2020-10-13,借阅状态:已还 - 借阅编号:100003,读者编号:321123,书籍编号:1001,借阅日期:2020-7-01,归还日期:NULL,借阅状态:过期 - 借阅编号:100004,读者编号:321124,书籍编号:2001,借阅日期:2020-10-09,归还日期:2020-10-14,借阅状态:已还 - 借阅编号:100005,读者编号:321124,书籍编号:0001,借阅日期:2020-10-15,归还日期:NULL,借阅状态:借阅 - 借阅编号:100006,读者编号:223411,书籍编号:2001,借阅日期:2020-10-16,归还日期:NULL,借阅状态:借阅 - 借阅编号:100007,读者编号:411111,书籍编号:1002,借阅日期:2020-9-01,归还日期:2020-9-24,借阅状态:已还 - 借阅编号:100008,读者编号:411111,书籍编号:0001,借阅日期:2020-9-25,归还日期:NULL,借阅状态:借阅 - 借阅编号:100009,读者编号:411111,书籍编号:1001,借阅日期:2020-10-08,归还日期:NULL,借阅状态:借阅
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值