本文使用的案例如下,一个类关系图
1 使用Dart和Java实现该类
类的分析
1 软件工程师和建筑工程师继承于工程师,工程师继承于工作者
2 美术教师和IT教师继承于教师,教师继承于工作者
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 {
}复制代码
Dart版本
//工作者
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是单继承,对于上面的简单场景无法体现出区别
2 场景拓展
赋予这些职业一些能力
类分析:
软件工程师和IT教师都具备修电脑的能力,建筑工程师和美术教师都具备手绘的能力,但是这些能力是他们特有的,不是工程师和教师具备的能力,所以不能在父辈中实现,这个时候就需要一个东西叫做接口。
Java版本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版本
abstract class CanFixComputer {
void fixComputer();
}
abstract class CanDesignSoftware {
void designSoftware();
}
//软件工程师
class SoftwareEngineer extends Engineer implements CanFixComputer, CanDesignSoftware {
void fixComputer() {
print('修电脑');
}
void designSoftware() {
print('设计软件');
}
}
//IT教师
class ITTeacher extends Teacher implements CanFixComputer {
void fixComputer() {
print('修电脑');
}
}复制代码
总结:
只有语法上的区别,Dart虽然没有接口,但是任何一个类就可以当作接口,所以本质上依然是一样的,
但是
如果使用Dart的Mixin思想去实现,是怎样的呢?
3 Mixin版本实现
1 封装修电脑能力和设计能力,使用factory关键字结合_权限符避免外部实例化和拓展
abstract class CanFixComputer {
factory CanFixComputer._() {
return null;
}
void fixComputer() {
print('修电脑');
}
}
abstract class CanDesignSoftware {
factory CanDesignSoftware._() {
return null;
}
void designSoftware() {
print('设计软件');
}
}复制代码
2 使用with//软件工程师
class SoftwareEngineer extends Engineer
with CanFixComputer, CanDesignSoftware {
}
//IT教师
class ITTeacher extends Teacher with CanFixComputer {
}复制代码
总结
每个具有某项特性的类不再需要具体去实现同样的功能,接口是没法实现功能的,而通过继承的方式虽然能实现功能,但已经有父类,同时不是一个父类,又不能多继承,所以这个时候,Dart的Mixin机制就比Java的接口会高效,开发上层的只需要关心当前需要什么特性,而开发功能模块的关心具体要实现什么功能。
4 顺序的问题
demo1
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();
}复制代码
输出
Son1
Son2复制代码
总结
优先级最高的总是类内实现的
demo2
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();
}复制代码
输出
Second
First复制代码
总结
可以看到,其实在Son2中implements只是说要实现他的doPrint()方法,这个时候其实具体实现是First中Mixin了具体实现。
而Mixin的具体顺序也是可以从代码倒过来看的,最后mixin的优先级是最高的。
最后的总结
1 Mixin将功能和类的上层设计分离,上层关心需要什么特性,开发功能模块关心具体实现什么功能
2 如果两个类继承于不同的父类但是有相同的功能,Mixin的优点就显示了出来