Mixin(织入)模式并不是GOF的《设计模式》归纳中的一种,但是在各种语言以及框架都会发现该模式(或者思想)的一些应用。简单来说,Mixin是带有全部实现或者部分实现的接口,其主要作用是更好的代码复用。本文将介绍Mixin的应用场景,以及关于继承、组合、多继承、接口的一些思考。

 

相关概念:

  前面提到,Mixin是有部分或者全部实现的接口,其主要作用是代码复用,需要理解这个简单的描述,需要先理清一些概念。

继承与组合:

  继承是面向对象的三大特征(封装、继承、多态),如果类A继承自类B,那么我们称A为子类(派生类),称B为父类(基类)。什么时候类A才能继承类B呢,可以说A是B的一种特殊化,英语来说就是A is a B,或者A is a kind of B。比如狗(dog)和动物(Animal)这两个抽象,dog is animal,这个是成立的,所以dog可以继承自animal。

  而组合代表的是其中一个类的对象是另一个类的对象的组成组合,英语来说,“has a”,比如人(People)这个类有一个属性addr是一个地址类(Address)的实例,就是说每个人都有一个地址。

  不管是继承还是组合,都起到了代码复用的作用,但又各有优缺点。上面继承和组合的例子都很明显,但有些情况就不那么容易区分两类事物是继承还是组合的关系了,或者说,两个类之间既可以用继承,又可以用组合,比如设计模式中的adapter模式,既可以类适配,又可以组合适配(对象适配)。

 

多继承与接口:

  在使用编程语言抽象事物之间的继承关系的时候,需要考虑对多继承的实现。所谓多继承就是说一个类有多个基类,举个简单的例子,dog是animal,同时dog又是runnable(可以跑动的对象)。多继承对于人类的思维来说是比较正常直观的,但是对于计算机编程语言,都会遇到一个绕不过去的问题,那就是菱形继承(diamond problem),下面这个图形象展示了什么时菱形继承:

  大学生就业培训,高中生培训,在职人员转行培训,企业团训

  从上图可以看到,类B、类C都继承了类A,类D同时继承了类B和类C,在继承关系上就形成了“菱形”--类D有两条路径到达类A。菱形问题带来什么问题呢,如果类A定义了某个方法foo,而且B和C都没有重写该方法,那么B和C都会有某种机制找到foo,那么对于D的实例在调用foo方法的时候,是调用到B中指向的foo方法还是C中指向的foo方法呢?

  菱形继承的问题会影响到语言的设计,一些编程语言支持多继承,如C++、python等等;另外一些则不支持多继承,如Java,ruby等。对于支持多继承的语言,为了解决菱形继承的问题,一般都会使用特定的方法,比如C++中的虚继承,python中的新式类的MRO。而对于不支持多继承的语言,一般使用某种接口(或者约定、协议)来实现多继承的功能,如Java中的interface,ruby中的include module。

 

duck typing:

  一个事物是不是鸭子(duck),如果

网友评论