关于flutter:Flutter-中不得不会的-mixin

5次阅读

共计 4115 个字符,预计需要花费 11 分钟才能阅读完成。

mixin 是 Dart 中十分重要的概念,对于未接触过此概念的 Coder 来说尤其重要,最近看源码的时候,因为对 mixin 不相熟导致了解呈现偏差,走了很多弯路,所以这篇文章介绍一下 mixin 概念。

Dart 及 Engine 版本:

Engine • revision ae90085a84
Tools • Dart 2.10.4

请留神版本,不同的版本可能存在差别。

先来看下官网的定义:

Mixins are a way of reusing a class’s code in multiple class hierarchies.

Mixins 是一种在多个类层次结构中重用类代码的办法。

在来看下 Wiki 的解释:

In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin’s methods depends on the language. Mixins are sometimes described as being “included” rather than “inherited”.

Mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (the “diamond problem”), or to work around lack of support for multiple inheritance in a language. A mixin can also be viewed as an interface with implemented methods. This pattern is an example of enforcing the dependency inversion principle.

翻译如下:

在面向对象的编程语言中,mixin(或 mix-in)是一个类,其中蕴含供其余类应用的办法,而不用成为其余类的父类。这些其余类如何取得对 mixin 办法的拜访权限取决于语言。混合素有时被形容为“蕴含”而不是“继承”。

Mixins 激励代码重用,并且可用于防止多重继承可能导致的继承歧义(“钻石问题”),或解决语言中对多重继承的反对有余的问题。混合也能够看作是已实现办法的接口。此模式是强制执行依赖关系反转原理的示例。

看完这两段介绍,可能仍然对其比拟含糊,不要紧,当初只需对其有个概念即可,上面会具体介绍 Mixins 的用法,我集体的了解就是:Mixins 解决了无奈多重继承的问题。

什么时候须要应用 Mixins

有如下场景:

定义一个基类人(Person),它有吃(eat)的办法。

有 3 个理论的人 A、B、C,它们都继承 Person,然而 3 集体有不同的技能:

  • A:会唱歌、跳舞
  • B:会跳舞、写代码
  • C:会唱歌、写代码

下面的场景中唱歌、跳舞、写代码是一种技能,并不是每一个人都会的,所以将其定义在 Person 中是不适合的,如果各自定义为一个类,又不能同时继承 Person 和唱歌、跳舞、写代码,如果将唱歌、跳舞、写代码定义为 Interface,那么 A、B、C 中要各自实现其办法,

那要如何实现呢?Mixins 出场啦。

定义一个 Person 基类和性能类唱歌、跳舞、写代码:

class Person {eat() {print('Person eat');
  }
}

class Dance {dance() {print('Dance dance');
  }
}

class Sing {sing() {print('Sing sing');
  }
}

class Code {code() {print('Code code');
  }
}

定义 A、B、C:

class A extends Person with Dance, Sing {}

class B extends Person with Sing, Code {}

class C extends Person with Code, Dance {}

留神:混合应用 with 关键字。

应用:

A a = A();
a.eat();
a.dance();
a.sing();

输入日志:

flutter: Person eat
flutter: Dance dance
flutter: Sing sing

能够看到 A 中有了 Dance 和 Sing 的相干的办法。

Dance 是一个 class,如果给其增加构造函数会如何?

给 Dance 增加构造函数,批改如下,

此时发现 A 和 C 无奈编译,呈现如下谬误:

很显著,须要 mixin 的类无奈定义构造函数。

所以个别会将须要 mixin 的类应用 mixin 关键字:

增加限定条件,应用关键字 on

接着下面的场景持续,这时定义一个狗的类,目前狗这个类也能够混合 Dance、Sing 和 Code,

class Dog with Code{}

然而,Code 是人类独有的技能,不心愿 Dog 这个类能够 mixin,所以给 Code 增加限定条件:

应用关键字 on 限定 Code 只能被 Person 或者其子类 mixin。

此时 Dog 无奈 mixin Code。

增加限定后,能够重写其办法,Code 重写 Person 的办法:

super 示意调用父类(Person)的办法。

如何解决多个类有同一办法的状况

假如有 D 和 D1 两个类,有同一个办法 d,E mixin D 和 D1:

此时,调用 e.d 办法:

E e = E();
e.d();

输入:

flutter: D1 d

阐明前面的将后面的笼罩了,调换下 D 和 D1 的程序:

class E with D1, D {}

输入:

flutter: D d

此时在 E 中也增加 d 办法:

输入:

flutter: E d

阐明 E 中 办法笼罩了原来的。

E 中 d 办法能够调用 super.d()

输入:

flutter: D d
flutter: E d

假如当初有 F、G、H 三个类,都有 a 办法,

有如下定义的类:

那么上面会输入什么值:

答案是:

flutter: G a

记住:混合类时,进行混合的多个类是线性的,这是他们共有办法不抵触的起因,混合的程序十分重要,因为它决定了混合时雷同的办法的解决逻辑。

再次看下 FG 的混合状况:

FG 继承 H,混合 F 和 G,对于雷同办法的优先级为:G > F > H,因而共有办法 a,最初执行的是 G 类中的 a 办法。

那么如果 FG 中也有 a 办法会如何?

如果自身(FG)也存在雷同的办法那么优先级:FG > G > F > H。super.a() 执行的是 G 中的 a 办法。

输入后果:

flutter: G a
flutter: FG a

更简单的来啦,请看如下混合关系:

BB 为一个抽象类,有一个构造函数,其中执行 init 办法,GB 和 PB 为一个混合类型,限定了只有 BB 或者其子类能力混合,WFB 继承 BB,并混合 GB、PB,此时创立 WFB 对象,

WFB wfb = WFB();

输入后果是什么?

flutter: BB Constructor
flutter: BB init
flutter: GB init
flutter: PB init

是不是很惊讶,依照下面的逻辑不是应该只调用 PB 的 init 办法吗?

你了解的没有错,确实只调用了 PB 的 init 办法,然而 PB 的 init 办法中调用了 super.init(),这个才是重点,PB 通过 super.init 调用到了 GB 中的 init 办法,GB 通过 super.init 调用到了 BB 中的 init 办法,所以最终输入的就是下面的后果。

这个肯定要了解其中的调用程序,因为的 Flutter Framework 的入口函数 runApp 中就是此模式:

WidgetsFlutterBinding.ensureInitialized 办法如下:

WidgetsFlutterBinding 混合结构如下:

class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {

BindingBase 及构造函数如下:

其执行了 initInstances 和 initServiceExtensions 办法。看上面混合的程序:

从后到前顺次执行其 initInstances 和 initServiceExtensions(如果有)办法,因为 initInstances 和 initServiceExtensions 办法中首先执行 super.initInstances()super.initServiceExtensions(),所以最初执行的程序为:BindingBase -> GestureBinding -> SchedulerBinding -> ServicesBinding -> PaintingBinding -> SemanticsBinding -> RendererBindinsg -> WidgetsBinding。

类型

还是下面的 F、G、H 三个类,那么 FG 的类型是什么,看上面的判断会输入什么?

输入:

flutter: FG is F : true
flutter: FG is G : true
flutter: FG is H : true

所以混合后的类型是超类的子类型。

总结

  1. Mixins 使咱们能够在无需继承父类的状况下为此类增加父类的“性能”,能够在同一个类中具备一个父级和多个 mixin 组件。
  2. Mixins 不能够申明任何构造函数。
  3. Mixins 增加限定条件应用 on 关键字。
  4. 混合应用 with 关键字,with 前面能够是 classabstract classmixin 的类型。
  5. Mixins 不是多重继承,相同,它只是在多个层次结构中重用类中的代码而无需扩大它们的一种形式。

交换

老孟 Flutter 博客(330 个控件用法 + 实战入门系列文章):http://laomengit.com

增加微信或者公众号支付《330 个控件大全》和《Flutter 实战》PDF。

欢送退出 Flutter 交换群(微信:laomengit)、关注公众号【老孟 Flutter】:

正文完
 0