原文在这里。写的不错,推荐各位看原文。
这里补充一下Mixin的定义:
只要一个类是继承自Object
的而且没有定义构造方法,那么这个类可以是一个Mixin了。当然,如果你想让mixin的定义更加的清晰,可以使用mixin关键字开头来定义。具体请参考这里
原文截图体会一下风格。
正文
在经典的面向对象编程语言里一定会有常规的类,抽象类和接口。当然,Dart也有它自己的接口,不过那是另外的文章要说的。有的时候阴影里潜伏者另外的野兽:Mixin!这是做什么的,如何使用?我们来一起发现。
没有mixin的世界
假设你在构建一个模拟野生动物的app,那么你需要一个Mosquito(蚊子)类。作为一个有预见性的开发人员,你会抽象蚊子们有的共通的东西然后放在一个抽象类里。
代码语言:javascript复制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方法了。代码冗余发生了!
代码语言:javascript复制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非常的简单:
代码语言:javascript复制mixin Fluttering {
void flutter() {
pring('fluttering');
}
}
这个mixin可以用在常规的类上面也可以用在抽象类,只需要一个with关键字。在野生动物模拟app例子里,你也许要用在抽象类上了。
代码语言:javascript复制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。
代码语言:javascript复制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内容请搜索ZaLou.Cn以前的文章或继续浏览下面的相关文章希望大家以后多多支持ZaLou.Cn!