类的单继承,是开发者再熟悉不过的继承方式,写起来也毫不费力。
而多继承呢,见得很多,写得很少。在很多的项目代码里,你还会见到一种很奇怪的类,他们有一个命名上的共同点,就是在类名的结尾,都喜欢用 Mixin。
1. 认识Mixin模式
那我们今天就来讲讲这个 Mixin,对于这个Mixin,如何理解?它其实是一种设计模式,如果开发者之间没有产生这样一种设计模式的共识,那么设计模式将不复存在。
为了让大家,对这个 Mixin 有一个更直观的理解,我摘录了网上一段说明。
继承是一个”is-a”关系。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?
答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。
怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?
这时候 Mixin 就闪亮登场了。飞行只是飞机做为交通工具的一种(增强)属性,我们可以为这个飞行的功能单独定义一个(增强)类,称之为 Mixin 类。这个类,是做为增强功能,添加到子类中的。为了让其他开发者,一看就知道这是个 Mixin 类,一般都要求开发者遵循规范,在类名末尾加上 Mixin 。
举个例子
class Vehicle(object): pass class PlaneMixin(object): def fly(self): print('I am flying') class Airplane(Vehicle, PlaneMixin): pass
使用Mixin类实现多重继承要遵循以下几个规范
- 责任明确:必须表示某一种功能,而不是某个物品;
- 功能单一:若有多个功能,那就写多个Mixin类;
- 绝对独立:不能依赖于子类的实现;子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。
2. 不使用Mixin的弊端
你肯定会问,不使用 Mixin 行吗?
当然可以,这个问题就像在问,我不遵循 PEP8 代码规范行吗?完全没问题,只是不推荐那样做。
那么到底有什么理由,让我们要去用到 Mixin 设计模式呢?
不使用的话,大概有如下三点弊端:
1、结构复杂
单继承中一个类的父类是什么,父类的父类是什么非常明确。多继承一个类有多个父类,父类又有多个父类,继承关系复杂。
2、优先顺序模糊
多个父类中有同名方法,在开发过程中,容易造成思维混乱,子类不知道继承哪个父类,会增加开发难度。关于子类的继承顺序,有一个比较复杂的 C3 算法,如果你还不清楚,可以点击我的另一篇文章 ,了解一下。
3、功能冲突
多重继承有多个父类,但是子类只能继承一个,对于同名方法,就会导致另一个父类的方法失效。