为什么需要Mix-in?
在学习面向对象时我们知道,类可以通过继承类获得属性和方法,通过继承可以减少重复代码、提高复用率。Python支持多继承,一个类可以通过继承多个类来得到它们的功能。但多继承会带来一些问题,比如属性冲突。那么有没有可能只继承类的方法呢?
当然方法名称也可能冲突。但如果合理地划分功能的话,这种可能性很小。
Mix-in类(混入类):只定义一些方法给子类使用,不定义自己的实例属性,也不要求调用它的__init__
方法。Mix-in类并不是新的语法,只是一种特殊的类,只用来提供方法。
在实际的代码中,我们经常会看到Mixin结尾的类(如
SingleObjectMixin
),这是一种命名约定,名称其实不会影响功能。
Mix-in 实例
这里借用 通过 Python 理解 Mixin 概念举的例子。
class MappingMixin:
def __getitem__(self, key):
return self.__dict__.get(key)
def __setitem__(self, key, value):
return self.__dict__.set(key, value)
class Person(MappingMixin):
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
p = Person("小陈", "男", 18)
print(p['name']) # "小陈"
print(p['age']) # 18
首先定义了一个Person
类,然后我们能用字典访问Person
,于是定义了一个只有方法的MappingMixin
类,并让Person
继承MappingMixin
的方法。
另一个例子 python 中Mixin混入类的用法:
class Tel:
def telfunc(self):
print("我可以接打电话")
class SMS:
def smsfunc(self):
print("我可以发短信")
class Phone(Tel, SMS):
def __init__(self, sn):
self.sn = sn
def welcome(self):
print("welcome {}".format(self.sn))
p = Phone("xiaomi")
p.telfunc()
p.smsfunc()
p.welcome()
Django中的Mix-in
Django中有很多Mixin类。在django.views.generic.base
中存在如下关系:
View
是一个基类(可以说是一个抽象基类),实现了核心功能如dispatch
。dispatch
委托具体子类的处理方法。
TemplateResponseMixin
为使用模板的视图提供了功能。
RedirectView
类只继承 View
,可以看到,它实现了 get
、head
、post
等方法。
TemplateView
只用于显示内容,因此它只实现了 get
方法。由于它需要相关的模板功能,所以继承了TemplateResponseMixin
。
Django中很多实现都依赖了Mix-in类,而我们在使用Django开发的时候,也可以利用(内置的和自定义的)Mix-in类提供功能。
django mixin文档
参考链接
- 通过 Python 理解 Mixin 概念
- python 中Mixin混入类的用法
- 《流畅的Python》第12章:继承的优缺点
- 《Effective Python》(第二版)41.考虑使用Mix-in Classes组合功能
- django mixin文档