今天应做的事没有做,明天再早也是耽误了。——裴斯泰洛齐
当我第一次接触Mixin的概念的时候,我是很茫然的,因为我之前一直都是使
用kotlin或者是java的语言开发项目的,这个知识点在这两种语言中根本是不存在的。不过,直到我开始使用它的时候,我才意识到它的强大。
为什么我们需要Mixin的特性呢?
如上这张图片很好理解,类比java来看呢,就是一个extends关系图。简单的介绍下,动物这个class有三个子类别,分别是鱼类,鸟类及哺乳动物,再继续就是各个类别的子类了。
哺乳动物的特性,鸟类的特性,鱼的特性,我们总结归纳下就是:哺乳,fly ,swim;既然是特性,我想,java的表示方式肯定是implement interface了,而每层与每层类别之间的关系,自然就是extends calss了。
哺乳动物中有具体的三种生物,那我抽象他们的特质为breast,而bird的特质就是fly,鱼就是swim吧。如果我们使用interfac的实现方式,那么我们需要每个具体的子类都去实现这个interface。而我们已经定义好了mammal,bird以及fish,假设,我们在他们中已经定义好了各自的方法,breast,fly和swim,那么,你们想想,我再去imple interface是不是就显得有点多余了呢?是不是现在代码很繁重呢?回答是,是的。那如何解决这种问题呢?
使用Mixin特性解决code reuse提升代码的简洁和层次感
Mixins are a way of reusing a class’s code in multiple class hierarchies.
**— ** dartlang.org
上面的问题我们自然要使用Mixin来进行解决了,写下简单的代码逻辑
class Animal{
}
class Mammal{
…
void breast();
}
class Bird{
…
void fly();
}
class Fish{
…
void swim();
}
class Dolphin extends Animal with Mammal
{}
Class Bat extends Animal with Mammal
{}
class Cat extends Animal with Mammal
{}
…
上面的示例中,我们可以发现我们reuse了Mammal Bird Fish类。这样我们就可以免去了定义接口interface的代码。是不是简洁了很多呢?
Mixin的一些约束
The mixin feature comes with a few restrictions (from dartlang.org ):
-
Dart 1.12版本或者更低的版本如果想要支持mixins,那么它必须继承object,同时,禁止调用super的方法。
-
Dart 1.13或更高版本支持可以从Object以外的类扩展的mixin,并且可以调用super.method()。默认情况下,仅在Dart VM和分析器中的标志后面提供此支持。更具体地说,它位于命令行分析器中的—supermixin标志的后面。它也可以在分析服务器中的客户端可配置选项后面使用。
Dart2js和dartdevc不支持超级混合。 -
在Dart 2.1中,mixin的限制较少。
例如,Flutter支持mixins调用super()并从Object以外的其他类进行扩展,但是语法有望在出现在所有Dart SDK中之前发生变化。
有关详细信息,[](sdk/mixin-declaration.md at master · dart-lang/sdk · GitHub)
基于以上几点,总结下来,一个mixin类的样子大致应该是这样的:
class A {
void behavior();
}
这个类就是一个mixin,通俗的讲,就是继承自object同时,没有调用super.method()。
如果我们想要阻止一个类被当作mixin调用,该如何操作呢?可以这样做:
class A{
factory A._()=> null;//这是一个命名构造方法
void behavior();
}
Mixin行为或者特质覆盖的问题
通过以上的介绍,基本mixin的使用差不多就要结束了,但是,我这里还是要赘述一点需要大家谨慎对待的问题。我直接上代码吧!
void main() {
String result = '';
AB ab = AB();
result += ab.getMessage();
BA ba = BA();
result += ba.getMessage();
print(result);
}
class AB extends P with A,B{
}
class BA extends P with B,A{
}
class P{
String getMessage()=> 'P';
}
class A{
String getMessage()=> 'A';
}
class B{
String getMessage()=> 'B';
}
大家可以猜想下这段代码的运行结果,这段代码A,B类以及P类中都有共同的方法getMessage(),他们分别会输出不同的值。AB,BA类分别with A,B和with B,A,最终的结果,我可以公布出来,是BA。大家想下,为什么会有这样的结果呢?
这里其实涉及到with的属性行为覆盖的问题,大家应该发现了顺序在这里是起到了关键的影响作用。是的,在不同的类中包含相同的属性行为的时候,extends或者implements中的属性行为会被with中的覆盖。而with如果mixin了多个类的时候,以最后的一个对象中的属性行为为最终的行为输出结果。
网友评论