Flutter 中 Dart的Mixin示例详解

原文在这里。写的不错,推荐各位看原文。

这里补充一下Mixin的定义:
只要一个类是继承自Object的而且没有定义构造方法,那么这个类可以是一个Mixin了。当然,如果你想让mixin的定义更加的清晰,可以使用mixin关键字开头来定义。具体请参考这里

原文截图体会一下风格。

正文

在经典的面向对象编程语言里一定会有常规的类,抽象类和接口。当然,Dart也有它自己的接口,不过那是另外的文章要说的。有的时候阴影里潜伏者另外的野兽:Mixin!这是做什么的,如何使用?我们来一起发现。

没有mixin的世界

假设你在构建一个模拟野生动物的app,那么你需要一个Mosquito(蚊子)类。作为一个有预见性的开发人员,你会抽象蚊子们有的共通的东西然后放在一个抽象类里。

abstract class Insect {
 void crawl() {
 print('crawling');
 }
}

abstract class AirborneInsect extends Insect {
 void flutter() {
 print('fluttering');
 }

 void buzz() {
 print('buzzing annoyingly')
 }
}

class Mosquito extends AirborneInsect {
 void doMosquitoThing() {
 crawl();
 flutter();
 buzz();
 print('sucking blood');
 }
}

很棒!你已经做到了!添加新的昆虫就如同微风拂过一样,根本不会有代码的冗余出现。。。一直到你发现你需要一个Swallow类(就是一种可以吃掉整个蚊子的东西)。

同样的也有很多鸟类共有的东西,我们可以创建一个Bird类。这个时候问题就出现了 -- 鸟也会振动翅膀!但是,你没法把flutter方法从AirboneInsect类里面提取出来组成一个新的类Fluttering。

为什么?Bird类可以继承Fluttering类,但是AirboneInsect不可以,它已经继承了Insect类了。Dart可不支持多继承(真很好)。

这下,你需要给Bird类添加一个flutter方法了。代码冗余发生了!

abstract class Bird {
 void chirp() {
 print('chirp chirp');
 }

 // Duplicate method
 void flutter() {
 print('fluttering');
 }
}

class Swallow extends Bird {
 void doSwallowThing() {
 chirp();
 flutter();
 print('eating a mosquito');
 }
}

使用mixin

Mixin的定义是“一种把类代码用在多个继承树的方法”。简单的说,mixin让你不用继承就可以引入代码块的方法。声明一个mixin非常的简单:

mixin Fluttering {
 void flutter() {
 pring('fluttering');
 }
}

这个mixin可以用在常规的类上面也可以用在抽象类,只需要一个with关键字。在野生动物模拟app例子里,你也许要用在抽象类上了。

mixin Fluttering {
 void flutter() {
 print('fluttering');
 }
}

abstract class Insect {
 void crawl() {
 print('crawling');
 }
}

abstract class AirborneInsect extends Insect with Fluttering {
 void buzz() {
 print('buzzing annoyingly');
 }
}

class Mosquito extends AirborneInsect {
 void doMosquitoThing() {
 crawl();
 flutter();
 buzz();
 print('sucking blood');
 }
}

abstract class Bird with Fluttering {
 void chirp() {
 print('chirp chirp');
 }
}

class Swallow extends Bird {
 void doSwallowThing() {
 chirp();
 flutter();
 print('eating a mosquito');
 }
}

也可以在一个类上面使用多个mixin。如果需要在Bird类上用一个chirping mixn的话,就和Fluttering mixin一起用就好。

abstract class Bird with Fluttering, Chirping

限制Mixin的使用

有的时候你不想让mixin用在早已存在的类上面,你只是想让它用在某些特定的类或者其子类上。这通常你的代码对早已存在的代码有依赖。

在野生动物app这个例子里,你发现仅仅支持swallow已经不够了。还有其他种类的鸟比如麻雀或者Blue Jay等。与麻雀不同,很多其他的鸟需要从地里面啄食,种子啊,虫子啊的。。。

给Bird抽象类添加方法是不可能的,因为不是所有的鸟都需要啄食。所以,为了避免代码冗余,你可以创建一个叫做Pecking的mixin。

mixin Pecking {
 void peck() {
 print('pecking');
 }
}

这至少比代码荣誉好很多了。但是,也会有人把这个mixin用在Insect类上。这样使用mixin问题就大了。

当你开始研究一个鸟类的动作的时候,你会发现鸟儿在逐出食物之后就会发出愉悦的鸟鸣。从当前的mixin里面调用chirp方法是不可能的。要改也非常简单,只要告诉Dart,Pecking mixin只能用在Bird类上面。现在调用Bird类的方法就没有问题了。

//...
mixin Pecking on Bird {
 void peck() {
 print('pecking');
 chirp();
 }
}

class Sparrow extends Bird with Pecking {}

class BlueJay extends Bird with Pecking {}

结论

Mixin对于继承体系中避免代码的冗余非常有用处。mixin也可以被约束在只可以用在某些特定的类上面,这让他们成为了开发的一大利器!

ps:下面在看下Flutter/Dart mixin类的理解

mixin是将一些有共同特性的类抽出来共用,把具体的特性封装成一个mixin供其他类使用。本质上是为了减少代码冗余。而implement也能实现这种功能,但是继承自implement的子类需要完全重写父类的所有属性与方法,这就造成了很多不必要的代码冗余。

mixin在使用上有如下特点:

mixin在定义时可以使用on关键字指定使用范围

mixin swim on fish {
 //具体实现
}

当多个mixin函数一样时,后一个mixin会覆盖前面一个(线性特征)

class S {
 fun()=>print('A');
}
mixin MA {
 fun()=>print('MA');
}
mixin MB {
 fun()=>print('MB');
}
class A extends S with MA,MB {}
class B extends S with MB,MA {}
======
main() {
A a = A();
a.fun();
B b = B();
b.fun();
}
=====
MB
MA
  • mixin可以实现蕾丝多重继承的功能,但是多重继承中相同函数执行并不会存在父子关系
  • mixin实现了一条继承链,声明的顺序代表了继承的顺序,声明在后面的mixin会最先执行
  • 而最终的子类与该继承链上所有类的类型(runtimeType)都能匹配上,即子类拥有所有mixin类的特性。

到此这篇关于Flutter 中 Dart的Mixin示例详解的文章就介绍到这了,更多相关Flutter Dart的Mixin内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Flutter中mixin的使用详解

    mixin是什么 mixin应该怎么理解呢,对Java系出身的我来说,这是一个新概念,各类资料的介绍也没找到一个清晰的定义.从个人理解来看,可以把它想象为Kotlin中的接口(和Java的区别是可以带非抽象的属性和方法),而多个mixin可以相互覆盖以实现组合,提供了非常大的灵活性,也可以达到类似多重继承的效果. 页表页面 这是一个普通的展示数据,上拉加载更多数据的列表. 其中有一个类型为List<T>的数据列表listData,有个page数据用于分页,isLoading用来判断是否正在加载

  • Flutter 中 Dart的Mixin示例详解

    原文在这里.写的不错,推荐各位看原文. 这里补充一下Mixin的定义: 只要一个类是继承自Object的而且没有定义构造方法,那么这个类可以是一个Mixin了.当然,如果你想让mixin的定义更加的清晰,可以使用mixin关键字开头来定义.具体请参考这里 原文截图体会一下风格. 正文 在经典的面向对象编程语言里一定会有常规的类,抽象类和接口.当然,Dart也有它自己的接口,不过那是另外的文章要说的.有的时候阴影里潜伏者另外的野兽:Mixin!这是做什么的,如何使用?我们来一起发现. 没有mixi

  • Android Flutter实现3D动画效果示例详解

    目录 前言 AnimatedWidget 简介 3D 旋转动画的实现 总结 前言 上一篇我们介绍了 Animation 和 AnimationController 的使用,这是最基本的动画构建类.但是,如果我们想构建一个可复用的动画组件,通过外部参数来控制其动画效果的时候,上一篇的方法就不太合适了.在 Flutter 中提供了 AnimatedWidget 组件用于构建可复用的动画组件.本篇我们用 AnimatedWidget 来实现组件的3D 旋转效果,如下图所示. AnimatedWidge

  • Flutter中数据库的使用教程详解

    在Flutter开发过程中,我门有时候需要对一些数据进行本地的持久化存储,使用sp文件形式虽然也能解决问题,但是有时数据量较大的时候,显然我们文件形式就不太合适了,这时候我们就需要使用数据库进行存储,我们知道在原生中有系统提供的轻量级sqlite数据库,在Flutter强大的生态环境中,也有这样一个数据库插件sqflite: ^2.0.2可以同时在Androud.iOS中进行数据库操作. 1. 创建数据库:这里我以存储我的搜索历史记录为例. 首先导入: import 'package:sqfli

  • Flutter状态管理Bloc使用示例详解

    目录 前言 两种使用模式 Cubit模式 最后 前言 目前Flutter三大主流状态管理框架分别是provider.flutter_bloc.getx,三大状态管理框架各有优劣,本篇文章将介绍其中的flutter_bloc框架的使用,他是bloc设计思想模式在flutter上的实现,bloc全程全称 business logic ,业务逻辑的意思,核心思想就是最大程度的将页面ui与数据逻辑的解耦,使我们的项目可读性.可维护性.健壮性增强. 两种使用模式 首先第一步引入插件: flutter_bl

  • Flutter之 ListView组件使用示例详解

    目录 ListView的默认构造函数定义 默认构造函数 ListView.builder ListView.separated 固定高度列表 ListView 原理 实例:无限加载列表 添加固定列表头 总结 ListView的默认构造函数定义 ListView是最常用的可滚动组件之一,它可以沿一个方向线性排布所有子组件,并且它也支持列表项懒加载(在需要时才会创建).我们看看ListView的默认构造函数定义: ListView({ ... //可滚动widget公共参数 Axis scrollD

  • Flutter Widget之FutureBuilder使用示例详解

    目录 正文 正文 本质上Flutter和Dart是异步的,Dart是Futures使你能够管理IO而不用担心线程或死锁. 例如,从应用程序外部加载数据需要时间,而Futures允许Dart先处理其他任务直到请求的数据可用. 但是涉及Future时,你如何构建Flutter小部件呢? 输入FutureBuilder,这是处理Futures的构造器 FutureBuilder( future: _data, builder: _myBuilderFunction, ) FutureBuilder让你

  • C语言中的正则表达式使用示例详解

    正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE).正则表达式是使用单个字符串来描述.匹配一系列符合某个句法规则的字符串. 在c语言中,用regcomp.regexec.regfree 和regerror处理正则表达式.处理正则表达式分三步: 编译正则表达式,regcomp: 匹配正则表达式,regexec: 释放正则表达式,regfree. 函数原型 /* 函数说明:Regcomp将正则表达式字符串regex编译

  • shrio中hashedCredentialsMatcher密码匹配示例详解

    类图如下: SimpleCredentialsMatcher是明文匹配,也是shrio框架默认的比对方式,网上的例子多是此方式.实际项目中,数据库中的密码一般是密文,此时密码的匹配需使用HashedCredentialsMatcher完成. 处理过程 在controller中通过Subject的login(token)将接收过来用户账号和密码(明文)交给shrio框架,示例代码如下 其次通过HashedCredentialsMatcher告诉shrio使用加密方式: 最后通过Authorizin

  • Java中的反射机制示例详解

    目录 反射 什么是Class类 获取Class实例的三种方式 通过反射创建类对象 通过反射获取类属性.方法.构造器 更改访问权限和实例赋值 运用场景 反射 反射就是把Java类中的各个成分映射成一个个的Java对象.即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法:对于任意一个对象,都能调用它的任意一个方法和属性.这种动态获取信息及动态调用对象方法的功能叫Java的反射机制 每一个Java程序执行必须通过编译.加载.链接和初始化四个阶段 1.编译:将.java.文件编译成字节码.

  • Python中图像算术运算的示例详解

    目录 介绍 算术运算:图像相加 算术运算:图像减法 位运算 介绍 还记得你在小学时学习如何加减数字吗?现在,你也可以对图像做同样的事情! 输入图像可以进行算术运算,例如加法.减法和按位运算(AND.OR.NOT.XOR).这些操作可以帮助提高输入照片的质量. 在本文中,你将了解使用 OpenCV Python 包对图像执行算术和按位运算的步骤.让我们开始吧! 对图像进行算术运算是什么意思? 因此,假设我们希望合并两张单独的照片中的两个像素.我们怎样才能将它们合并? 让我们想象以下场景.第一个像素

随机推荐