2019独角兽企业重金招聘Python工程师标准>>>

Dart语言集合了现代编程语言的众多优点,Mixin继承机制也是其一。但针对Java程序员来说,可能不是一下子能理解的,比如我第一次看到的时候,也迷迷糊糊了半天——这是啥玩意???

要说Mixin,可能写成MixIn会更好理解,翻译回来就是混入,当然你执意说这是一种“迷信”继承机制,那也没辙。

下面将从一个实际情景入手,对比Java和Dart的实现,以便更好理解Dart的mixin。

场景

我们先来描绘这么一个职业关系图:

职业关系图

从图中可以梳理出以下关系:

工程师类目,有软件工程师和建筑工程师师等,他们共同点都是工程师

教师类目有美术教师,IT教师等,他们共同点都是教师

而以上的工程师、教师都是社会的工作者。

那么接下来我们分别使用Java和Dart来实现这个关系类。

注意:接下来的这篇文章中为了方便表达意义,将所有类写在一个文件里面,请暂时忽略代码不规范细节。并且Dart在本文不会使用语法糖写法。

Java版本实现

从层级出发,可以写出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也是单继承。

因为上面的场景是在是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类。

java mixin_理解Dart的Mixin继承机制相关推荐

  1. JavaScript大杂烩4 - 理解JavaScript对象的继承机制

    JavaScript是单根的完全面向对象的语言 JavaScript是单根的面向对象语言,它只有单一的根Object,所有的其他对象都是直接或者间接的从Object对象继承.而在JavaScript的 ...

  2. java 判断object类型_Java 类继承机制

    封装.继承.多态是面向对象的三大特征,"继承"最主要的目的是为了实现代码的可复用性.通过父类与子类的继承关系,子类继承了父类的成员函数和成员变量,提高了代码的重复利用率.同时,子类 ...

  3. 深入理解 Dart 中的继承和 Minxins

    上一篇文章中我们详细地介绍了 Dart 中的面向对象的基础,这一篇文章中我们继续探索 Dart 中面向对象的重点和难点(继承和 Mixins).Mixins(混合)特性是很多语言中都是没有的.这篇文章 ...

  4. Javascript继承机制的设计思想

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

  5. 初步理解Java的三大特性——封装、继承和多态

    声明:整理自网络,如有雷同,请联系博主处理 一.封装 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被 ...

  6. 深入理解Java类型信息(Class对象)与反射机制

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java并发之synchronize ...

  7. 在java继承机制中 父类中的私有_Java中子类能继承父类的私有属性吗?

    前段时间去听老师讲课的时候,老师告诉我子类是可以继承父类所有的属性和方法的.当时我是极其疑惑的,因为之前学校考试时这个考点我记得很清楚:子类只能继承父类的非私有属性和方法.老师给我的解释是这样的--先 ...

  8. Java基础复习——继承机制

    一.写在前面 1.基本作用 代码复用,更重要的就是有了继承机制后才会有后面的"方法重写"和"多态机制". 2.语法格式 //Student类继承了Person类 ...

  9. java看不起c语言,为什么我感觉Java比C语言难呢?总觉得逻辑上没有C语言好理解。比如各种继承介面。包之间的关系。...

    为什么我感觉Java比C语言难呢?总觉得逻辑上没有C语言好理解.比如各种继承介面.包之间的关系.以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我 ...

最新文章

  1. WKWebView 那些坑
  2. 抽成 30% 的苹果税是良心价?谷歌也学“坏”了
  3. 网站运营活动总结报告模板
  4. Zuul 2 : The Netflix Journey to Asynchronous, Non-Blocking Systems--转
  5. php获取xml某个节点的所有内容,怎样输出XML所有的同名节点内容?
  6. IDEA中SpringBoot中使用单元测试Junit方法
  7. typecho 去掉index.php,typecho如何去掉index.php
  8. Vue 消除Token过期时刷新页面的重复提示
  9. Python sorted() 函数
  10. 反向传播算法的详细解释(下)
  11. 总结前端常用控件和疑难杂症的解决方法
  12. php课后题,知到PHP语言程序设计课后习题答案
  13. php大m大d,ThinkPHP中M方法与D方法区别
  14. JAVA集合系列(1):集合的整体框架
  15. 推荐一款好用的取色器(仅支持windows)
  16. XMPP即时通讯协议使用(十)——好友关系状态
  17. PMP第六章:项目进度管理
  18. 致远互联开始向云端生态发力奔跑
  19. 单向流动的拓扑结构_六种基本网络拓扑结构
  20. 阅读源码-理解torch.utils.data、torch.utils.data.Dataset、torch.utils.data.DataLoader的工作方式

热门文章

  1. Mastodon 生产部署指南
  2. 如何做好沙漠旅游规划和沙漠旅游开发?
  3. Mybatis中sql语句(大于,小于,等于,不等于
  4. python3 urllib3_Python urllib3.disable_warnings方法代码示例
  5. Unity Shader Fresnel 菲涅尔反射
  6. Fluent中单精度和双精度区别
  7. 吴恩达:AI的下一个发展方向,从大数据转向小数据
  8. 收集的一些读之有意的话
  9. 卫生间吊顶集成好还是石膏板好
  10. 分享一款绘制时序图的实用小工具