在Python编程中,Mark Lutz提到了术语mixin。我有C/ c++ / c#的背景,以前没有听说过这个术语。什么是mixin?
从这个例子的字里行间(我链接了这个例子,因为它很长),我假设这是一个使用多重继承来扩展类的情况,而不是适当的子类化。这样对吗?
为什么我要这样做,而不是把新功能放到一个子类?就此而言,为什么混合/多重继承方法会比使用组合更好呢?
mixin与多重继承的区别是什么?这只是语义上的问题吗?
在Python编程中,Mark Lutz提到了术语mixin。我有C/ c++ / c#的背景,以前没有听说过这个术语。什么是mixin?
从这个例子的字里行间(我链接了这个例子,因为它很长),我假设这是一个使用多重继承来扩展类的情况,而不是适当的子类化。这样对吗?
为什么我要这样做,而不是把新功能放到一个子类?就此而言,为什么混合/多重继承方法会比使用组合更好呢?
mixin与多重继承的区别是什么?这只是语义上的问题吗?
当前回答
mixin是一种特殊的多重继承。使用mixin的主要情况有两种:
您希望为类提供大量可选特性。 你想在很多不同的类中使用一个特定的特性。
对于第一个例子,考虑werkzeug的请求和响应系统。我可以这样创建一个普通的request对象:
from werkzeug import BaseRequest
class Request(BaseRequest):
pass
如果我想添加接受报头支持,我会这样做
from werkzeug import BaseRequest, AcceptMixin
class Request(AcceptMixin, BaseRequest):
pass
如果我想让一个请求对象支持接受头,标签,身份验证和用户代理支持,我可以这样做:
from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin
class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
pass
区别是微妙的,但是在上面的例子中,mixin类并不是独立存在的。在更传统的多重继承中,AuthenticationMixin(例如)可能更像Authenticator。也就是说,这个类可能被设计成独立存在的。
其他回答
我读到你有c#背景。因此,一个好的起点可能是。net的mixin实现。
你可能想在http://remix.codeplex.com/上查看codeplex项目
请观看lang.net Symposium链接以获得概述。codeplex页面上还有更多的文档。
问候 斯特凡
也许ruby中的一个例子会有所帮助:
你可以包含mixin Comparable并定义一个函数"<=>(other)", mixin提供了所有这些函数:
<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)
它通过调用<=>(other)并返回正确的结果来实现这一点。
"instance <=> other"如果两个对象相等则返回0,如果instance大于other则返回小于0,如果other大于0则返回大于0。
也许举几个例子会有所帮助。
如果您正在构建一个类,并且希望它像字典一样工作,那么您可以定义所有必要的__ __方法。但这有点麻烦。作为一种替代方法,您可以只定义一些,并从UserDict继承(除了任何其他继承)。DictMixin(移动到集合。py3k中的DictMixin)。这将自动定义字典api的所有其余部分。
第二个例子:GUI工具包wxPython允许您创建具有多列的列表控件(例如,在Windows资源管理器中显示的文件)。默认情况下,这些列表相当基本。您可以添加额外的功能,例如通过单击列标题按特定列对列表进行排序的功能,可以从ListCtrl继承并添加适当的mixins。
mixin是一种特殊的多重继承。使用mixin的主要情况有两种:
您希望为类提供大量可选特性。 你想在很多不同的类中使用一个特定的特性。
对于第一个例子,考虑werkzeug的请求和响应系统。我可以这样创建一个普通的request对象:
from werkzeug import BaseRequest
class Request(BaseRequest):
pass
如果我想添加接受报头支持,我会这样做
from werkzeug import BaseRequest, AcceptMixin
class Request(AcceptMixin, BaseRequest):
pass
如果我想让一个请求对象支持接受头,标签,身份验证和用户代理支持,我可以这样做:
from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin
class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
pass
区别是微妙的,但是在上面的例子中,mixin类并不是独立存在的。在更传统的多重继承中,AuthenticationMixin(例如)可能更像Authenticator。也就是说,这个类可能被设计成独立存在的。
这个概念来自Steve 's Ice Cream,这是一家由Steve Herrell于1973年在马萨诸塞州萨默维尔创立的冰淇淋店,在那里混合(糖果、蛋糕等)被混合成基本的冰淇淋口味(香草、巧克力等)。
受到Steve 's Ice Cream的启发,Lisp对象系统Flavors的设计者第一次在编程语言中包含了这个概念,其中mix-in是用于增强其他类的小型辅助类,flavour是大型独立类。
因此,主要的思想是mix-in是一个可重用的扩展(“可重用”而不是“独占”;' extension '而不是' base ')。
这个概念与单一或多个继承以及抽象或具体类的概念是正交的。混合类可以用于单个或多个继承,可以是抽象类也可以是具体类。混合类有不完整的接口,抽象类有不完整的实现,具体类有完整的实现。
Mix-in类名通常以' -MixIn '、' -able '或' -ible '作为后缀,以强调它们的性质,就像Python标准库中socketserver模块的ThreadingMixIn和ForkingMixIn类,以及集合的Hashable、Iterable、Callable、Awaitable、AsyncIterable和可逆类一样。美国广播公司(abc)模块。
下面是一个mix-in类的例子,用于扩展Python内置list和dict类的日志记录功能:
import logging
class LoggingMixIn:
def __setitem__(self, key, value):
logging.info('Setting %r to %r', key, value)
super().__setitem__(key, value)
def __delitem__(self, key):
logging.info('Deleting %r', key)
super().__delitem__(key)
class LoggingList(LoggingMixIn, list):
pass
class LoggingDict(LoggingMixIn, dict):
pass
>>> logging.basicConfig(level=logging.INFO)
>>> l = LoggingList([False])
>>> d = LoggingDict({'a': False})
>>> l[0] = True
INFO:root:Setting 0 to True
>>> d['a'] = True
INFO:root:Setting 'a' to True
>>> del l[0]
INFO:root:Deleting 0
>>> del d['a']
INFO:root:Deleting 'a'