在Programming Python中,Mark Lutz提到了mixin这个术语。我来自C / C++ / C#背景,以前从未听说过这个词。什么是混合?
阅读此示例的行间(我已经链接到它,因为它很长),我假设这是使用多重继承来扩展类而不是适当的子类的情况。这是对的吗?
为什么我要这样做而不是将新功能放入子类中?就此而言,为什么混合/多重继承方法比使用组合更好?
混合与多重继承的区别是什么?这只是语义问题吗?
网友回答:
首先,您应该注意,mixins 仅存在于多继承语言中。你不能在Java或C#中进行混音。
基本上,mixin 是一种独立的基本类型,它为子类提供有限的功能和多态共振。如果您正在考虑 C#,请考虑一个您不必实际实现的接口,因为它已经实现;您只需从中继承并从其功能中受益即可。
混合通常范围很窄,并不意味着要扩展。
[编辑 — 关于原因:]
我想我应该解决为什么,既然你问了。最大的好处是你不必一遍又一遍地自己做。在 C# 中,混合可以从处置模式中受益的最大位置。每当您实现 IDisposable 时,您几乎总是希望遵循相同的模式,但您最终会编写和重新编写相同的基本代码,但略有变化。如果有可扩展的处置混合,您可以节省很多额外的打字时间。
[编辑 2 — 回答您的其他问题]
混合与多重继承的区别是什么?这只是语义问题吗?
是的。mixin 和标准多重继承之间的区别只是语义问题;具有多重继承的类可能会使用 mixin 作为该多重继承的一部分。
mixin 的要点是创建一个类型,该类型可以通过继承“混合”到任何其他类型,而不会影响继承类型,同时仍为该类型提供一些有益的功能。
同样,考虑一个已经实现的接口。
我个人不使用mixins,因为我主要使用不支持它们的语言进行开发,所以我很难想出一个像样的例子来为你提供“啊哈!”的时刻。但我会再试一次。我将使用一个人为的例子——大多数语言已经以某种方式提供了这个功能——但希望这将解释应该如何创建和使用 mixins。这里是:
假设您有一个类型,您希望能够序列化到 XML 和从 XML 序列化。您希望该类型提供一个“ToXML”方法,该方法返回一个字符串,其中包含一个包含该类型的数据值的 XML 片段,以及一个“FromXML”,该方法允许该类型从字符串中的 XML 片段重建其数据值。同样,这是一个人为的示例,因此您可能使用文件流或语言运行时库中的 XML 编写器类…无论什么。关键是您希望将对象序列化为 XML,并从 XML 中获取新对象。
此示例中的另一个重要点是您希望以通用方式执行此操作。您不希望必须为要序列化的每个类型实现“ToXML”和“FromXML”方法,您需要一些通用方法来确保您的类型将执行此操作并且它正常工作。您希望代码重用。
如果您的语言支持它,您可以创建 XmlSerializable mixin 来为您完成工作。此类型将实现 ToXML 和 FromXML 方法。它将使用一些对示例不重要的机制,能够从与它混合的任何类型的类型中收集所有必要的数据,以构建 ToXML 返回的 XML 片段,并且同样能够在调用 FromXML 时恢复该数据。
和。。就是这样。若要使用它,您需要将任何需要序列化为 XML 继承的类型 XmlSerializable。每当需要序列化或反序列化该类型时,只需调用 ToXML 或 FromXML。事实上,由于 XmlSerializable 是一个成熟的类型和多态的,因此您可以设想构建一个文档序列化程序,它对原始类型一无所知,只接受 XmlSerializable 类型的数组。
现在想象一下将此方案用于其他事情,例如创建一个 mixin,以确保混合它的每个类都记录每个方法调用,或者创建一个 mixin,为混合它的类型提供事务性。这个清单可以继续下去。
如果您只是将 mixin 视为一种小型基本类型,旨在向类型添加少量功能而不会以其他方式影响该类型,那么您就是黄金。
希望。🙂
网友回答:
混合是一种特殊的多重继承。使用混合有两种主要情况:
对于第一个示例,请考虑werkzeug的请求和响应系统。我可以通过说来制作一个普通的旧请求对象:
from werkzeug import BaseRequest
class Request(BaseRequest):
pass
如果我想添加接受标头支持,我会这样做
from werkzeug import BaseRequest, AcceptMixin
class Request(AcceptMixin, BaseRequest):
pass
如果我想创建一个支持接受标头、etags、身份验证和用户代理支持的请求对象,我可以这样做:
from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin
class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
pass
区别是微妙的,但在上面的例子中,mixin 类并不是独立存在的。在更传统的多重继承中,(例如)可能更像 .也就是说,该类可能会被设计为独立存在。AuthenticationMixin
Authenticator
网友回答:
这个答案旨在通过以下示例来解释混合:
它还应审议有争议的问题:
多重继承是否有必要表征混合蛋白?
定义
我还没有看到来自“权威”来源的引用清楚地说明什么是 Python 中的混合。
我已经看到了 mixin 的 2 种可能定义(如果它们被认为与其他类似概念(如抽象基类)不同),人们并不完全同意哪一个是正确的。
不同语言的共识可能有所不同。
定义1:无多重继承
mixin 是一个类,使得该类的某些方法使用类中未定义的方法。
因此,该类不是要实例化,而是用作基类。否则,实例将具有在不引发异常的情况下无法调用的方法。
一些来源添加的一个约束是该类可能不包含数据,只包含方法,但我不明白为什么这是必要的。然而,在实践中,许多有用的mixin没有任何数据,而没有数据的基类更容易使用。
一个典型的例子是仅从和实现所有比较运算符:<=
==
class ComparableMixin(object):
"""This class has methods which use `<=` and `==`,
but this class does NOT implement those methods."""
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return self <= other and (self != other)
def __gt__(self, other):
return not self <= other
def __ge__(self, other):
return self == other or self > other
class Integer(ComparableMixin):
def __init__(self, i):
self.i = i
def __le__(self, other):
return self.i <= other.i
def __eq__(self, other):
return self.i == other.i
assert Integer(0) < Integer(1)
assert Integer(0) != Integer(1)
assert Integer(1) > Integer(0)
assert Integer(1) >= Integer(1)
# It is possible to instantiate a mixin:
o = ComparableMixin()
# but one of its methods raise an exception:
#o != o
这个特殊的例子可以通过装饰器来实现,但这里的游戏是重新发明轮子:functools.total_ordering()
import functools
@functools.total_ordering
class Integer(object):
def __init__(self, i):
self.i = i
def __le__(self, other):
return self.i <= other.i
def __eq__(self, other):
return self.i == other.i
assert Integer(0) < Integer(1)
assert Integer(0) != Integer(1)
assert Integer(1) > Integer(0)
assert Integer(1) >= Integer(1)
定义2:多重继承
mixin 是一种设计模式,其中基类的某些方法使用它未定义的方法,并且该方法旨在由另一个基类实现,而不是像定义 1 中那样由派生类实现。
术语mixin类是指旨在用于该设计模式的基类(TODO那些使用该方法的基类,还是那些实现它的人?
确定给定的类是否是mixin并不容易:该方法可以在派生类上实现,在这种情况下,我们回到定义1。你必须考虑作者的意图。
这种模式很有趣,因为可以将功能与不同的基类选择重新组合:
class HasMethod1(object):
def method(self):
return 1
class HasMethod2(object):
def method(self):
return 2
class UsesMethod10(object):
def usesMethod(self):
return self.method() + 10
class UsesMethod20(object):
def usesMethod(self):
return self.method() + 20
class C1_10(HasMethod1, UsesMethod10): pass
class C1_20(HasMethod1, UsesMethod20): pass
class C2_10(HasMethod2, UsesMethod10): pass
class C2_20(HasMethod2, UsesMethod20): pass
assert C1_10().usesMethod() == 11
assert C1_20().usesMethod() == 21
assert C2_10().usesMethod() == 12
assert C2_20().usesMethod() == 22
# Nothing prevents implementing the method
# on the base class like in Definition 1:
class C3_10(UsesMethod10):
def method(self):
return 3
assert C3_10().usesMethod() == 13
权威的 Python 实例
在collections.abc的官方文档中,文档明确使用了术语Mixin Methods。
它指出,如果一个类:
__next__
Iterator
然后该类免费获得一个 mixin 方法。__iter__
因此,至少在文档的这一点上,mixin 不需要多重继承,并且与定义 1 一致。
当然,文档在不同点上可能是矛盾的,其他重要的 Python 库可能在其文档中使用其他定义。
本页也使用了术语,这清楚地表明类喜欢并且可以称为Mixin类。Set mixin
Set
Iterator
其他语言
virtual
=0
定义 2 可以通过虚拟继承实现:从两个派生类进行多重继承
模板简介:该模板名称为【什么是mixin,为什么它有用?】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Python】栏目查找您需要的精美模板。