Dart语言集合了现代编程语言的众多优势,Mixin继承机制也是其一。但针对Java程序员来讲,可能不是一会儿能理解的,好比我第一次看到的时候,也迷迷糊糊了半天——这是啥玩意???java
要说Mixin,可能写成MixIn会更好理解,翻译回来就是混入,固然你执意说这是一种“迷信”继承机制,那也没辙。git
下面将从一个实际情景入手,对比Java和Dart的实现,以便更好理解Dart的mixin。程序员
咱们先来描绘这么一个职业关系图:
github
职业关系图编程
从图中能够梳理出如下关系:编程语言
而以上的工程师、教师都是社会的工做者。ide
那么接下来咱们分别使用Java和Dart来实现这个关系类。ui
注意:接下来的这篇文章中为了方便表达意义,将全部类写在一个文件里面,请暂时忽略代码不规范细节。而且Dart在本文不会使用语法糖写法。spa
从层级出发,能够写出Java版本实现以下:翻译
//工做者 abstract class Worker { public abstract void doWork();//工做者须要工做 } //工程师 class Engineer extends Worker { @Override public void doWork() { System.out.println("工程师在工做"); } } //教师 class Teacher extends Worker { @Override public void doWork() { System.out.println("教师在教学"); } } //软件工程师 class SoftwareEngineer extends Engineer { } //建筑工程师 class BuildingEngineer extends Engineer { } //美术教师 class ArtTeacher extends Teacher { } //IT教师 class ITTeacher extends Teacher { }
//工做者 abstract class Worker { void doWork();//工做者须要工做 } //工程师 class Engineer extends Worker { void doWork() { print('工程师在工做'); } } //教师 class Teacher extends Worker { void doWork() { print('教师在教学'); } } //软件工程师 class SoftwareEngineer extends Engineer { } //建筑工程师 class BuildingEngineer extends Engineer { } //美术教师 class ArtTeacher extends Teacher { } //IT教师 class ITTeacher extends Teacher { }
从上面实现能够看出,两个实现并没什么卵区别好咩。。。。。。
嗯,目前来讲确实是这样的,由于Dart也是单继承。
由于上面的场景是在是too young too simple了,下面开始扩展一些场景。
仍是刚刚那张关系图,咱们开始思考这些职业他们都具备什么能力。
因而我给这些职业虚拟了如下能力:
职业 | 能力 |
---|---|
软件工程师 | 软件设计、修电脑 |
建筑工程师 | 手绘 |
美术教师 | 手绘、书法 |
IT教师 | 修电脑 |
他们的关系图以下:
经过图形或表格能够看出,软件工程师和IT教师都具有修电脑的能力,建筑工程师和美术教师都具有手绘的能力,可是这些能力都是他们特有的,不是工程师或者教师具有的能力,因此不能在他们的父类中实现。
那么这个时候咱们就考虑到一个东西——接口。
以软件工程师和IT教师为例:
他们都具有修电脑的能力:
interface CanFixComputer { void fixComputer(); } interface CanDesignSoftware { void designSoftware(); } //软件工程师 class SoftwareEngineer extends Engineer implements CanFixComputer, CanDesignSoftware { @Override public void fixComputer() { System.out.println("修电脑"); } @Override public void designSoftware() { System.out.println("设计软件"); } } //IT教师 class ITTeacher extends Teacher implements CanFixComputer { @Override public void fixComputer() { System.out.println("修电脑"); } }
至关标准的实现了
咱们知道Dart是没有interface这种东西的,但并不觉得着这门语言没有接口,事实上,Dart任何一个类都是接口,你能够实现任何一个类,只须要重写那个类里面的全部具体方法。
咱们只须要将上面的interface 修改为 abstract class,就是dart中的实现了。
可是咱们发现,fixComputer这个接口被继承了两次,而且两次的实现都是同样的,这里就出现了代码重复和冗余的问题。怎么办呢?在java中咱们有接口的default实现来解决这个问题(这是一个java8出现的不得已的方案。)
这个时候mixin的做用就出现了
abstract class CanFixComputer { void fixComputer() { print('修电脑'); } } abstract class CanDesignSoftware { void designSoftware() { print('设计软件'); } } //软件工程师 class SoftwareEngineer extends Engineer with CanFixComputer, CanDesignSoftware { } //IT教师 class ITTeacher extends Teacher with CanFixComputer { } main() { ITTeacher itTeacher = new ITTeacher(); itTeacher.doWork(); itTeacher.fixComputer(); SoftwareEngineer softwareEngineer = new SoftwareEngineer(); softwareEngineer.doWork(); softwareEngineer.fixComputer(); softwareEngineer.designSoftware(); }
能够看到,这里再也不用implements
,更不是extends
,而是with
。
并且,每一个具备某项特性的类再也不须要具体去实现一样的功能,接口是无法实现功能的,而经过继承的方式虽然能实现功能,但已经有父类,同时不是一个父类,又不能多继承,因此这个时候,Dart的Mixin机制就比Java的接口会高效,开发上层的只须要关心当前须要什么特性,而开发功能模块的关心具体要实现什么功能。
既然是with,那应该也会有顺序的区别,
思考一个问题:若是同时with两个类,但两个类中有一样的一个方法的不一样实现,那么这个时候应该使用的是哪个类的方法?
下面以一个简单的Demo来讲明这个问题:
class First { void doPrint() { print('First'); } } class Second { void doPrint() { print('Second'); } } class Father { void doPrint() { print('Father'); } } class Son1 extends Father with First,Second { void doPrint() { print('Son1'); } } class Son2 extends Father with First implements Second { void doPrint() { print('Son2'); } } main() { Son1 son1 = new Son1(); son1.doPrint(); Son2 son2 = new Son2(); son2.doPrint(); }
那么这个程序运行后,将会在控制台输出以下:
1 2 |
Son1 Son2 |
能够看到,不管是extends、implements仍是mixin,优先级最高的是在具体类中的方法。
咱们稍微改一下上面的例子:
class First { void doPrint() { print('First'); } } class Second { void doPrint() { print('Second'); } } class Father { void doPrint() { print('Father'); } } class Son1 extends Father with First,Second { } class Son2 extends Father with First implements Second { } main() { Son1 son1 = new Son1(); son1.doPrint(); Son2 son2 = new Son2(); son2.doPrint(); }
这个时候控制台输出以下:
1 2 |
Second First |
能够看到,其实在Son2中implements只是说要实现他的doPrint()
方法,这个时候其实具体实现是First中Mixin了具体实现。
而Mixin的具体顺序也是能够从代码倒过来看的,最后mixin的优先级是最高的。
PS: dart中有个关键字 mixin 能够用来替换上面的 class,这个类表示专门用来作mixin的。
另外在mixin类中咱们还以使用这样使用
mixin MusicalPerformer on Musician { // ··· }
这个表示只有类Musician可以使用这个mixin类。