在Python中,mixin是否等同于合成?如果是这样的话,为什么不直接使用构图呢?

在Python中,mixin是否等同于合成?如果是这样的话,为什么不直接使用构图呢?,python,inheritance,mixins,composition,Python,Inheritance,Mixins,Composition,我把mixin理解为看起来像是继承,但更像是合成。 (编辑:我倾向于认为通过mixin提供额外的功能/属性,而不是提供另一个is-a关系) 在精神上,当我使用mixin时,我是这样说的:我给你这个mixin,而不是你实际上也是这个mixin类型 我读了几遍,你应该更喜欢写作而不是继承 我们可以直接使用合成而不是混合,混合的目的是什么 如果非要我猜的话,那是因为我的\u instance.foo()比我的\u instance.foo()更容易。另一个\u instance.foo()? (如果m

我把mixin理解为看起来像是继承,但更像是合成。
(编辑:我倾向于认为
通过mixin提供额外的功能/属性
,而不是
提供另一个is-a关系

在精神上,当我使用mixin时,我是这样说的:我给你这个mixin,而不是你实际上也是这个mixin类型

我读了几遍,你应该更喜欢写作而不是继承

我们可以直接使用合成而不是混合,混合的目的是什么

如果非要我猜的话,那是因为我的\u instance.foo()比我的\u instance.foo()更容易。另一个\u instance.foo()?
(如果mixin有foo(),则可以使用my_instance.foo(),在将另一个_实例合成为my_实例的属性时,需要my_instance.other_instance.foo())

还有其他原因吗


编辑:

所以,即使我觉得这是一种,混合仍然是一种关系。当您使用is-a here-is,cleaner接口时,您将得到好处。这就是我对德尔南答案的解释

(因为mixin没有给你一个is-a关系,它给你一个has-a)

错了,它确实给了你一种“是-是”的关系。考虑<代码>类C(a,b)< /代码>。code>issubclass(C,A)是真的,
issubclass(C,B)
也是真的。调用
C()。属性access
C().attr\u of_{a,b}
也为您提供了
a
b
的属性(与方法的警告相同)

我读了几遍,你应该更喜欢写作而不是继承

这种经验法则的存在是因为许多人倾向于在不合适的地方使用继承,而不是因为继承在任何情况下都不是一种有用的工具。这也适用于Python。常见(良好)原因包括:

  • is-A关系可能是错误的,例如,因为它违反了Liskov替代原则。这一原因不受mixin的影响,见上文
  • 由于各种原因,组合更容易或更不容易出错。当mixin也是可能的时候,这个理由是有效的,如果有什么需要放大的话,因为要正确地获得MRO和
    super()
    调用序列可能有点棘手()
如果非要我猜的话,那是因为我的_instance.foo()比我的_instance.foo()更容易。另一个_instance.foo()

这只是几个额外的字符。更重要的是,您必须为要重新导出的每个方法重新键入包装器方法(如果您通过组合模拟is-a关系,则所有方法都是这样)


从概念上讲,如果
C
实际上是-a
a
,那么这项手工工作似乎毫无意义,而且容易出错。mixin/multiple继承支持这样的情况:一个对象超过了一个bass类可以或应该表示的内容。例如,UTF-8字符串既可以是
ByteBuffer
,也可以是
unicodeseam
。一般来说,我们对此有接口(或者没有;在Python中,这是隐式的),但Mixin还允许以可组合和方便的方式添加相关功能。

Mixin只是多重继承的不同名称,而不是组合。实际上,您应该说“合理的多重继承”,因为mixin类被设计用于多重继承。我真的不知道mixin在哪里提供了has-a关系和is-a关系。顺便说一下:使用
\uu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
而不是
myuuuuuuuuuuuuuu,它确实给了你一种is-a关系。
OK。我写得不清楚。让我换一句话:Mixin更像是has-a而不是is-a,因为它提供了一个原始类所没有的功能。@eugene我想我知道你来自哪里,但我不认为这是一种有用的思考方式。没有一个“原始类”。有几个基类,派生类从每个基类继承了一些位。可能会产生误导的是,如果你认为“我的类有一个行为”,并且基于“有一个”这个词,你会错误地认为你在使用组合。拥有一种行为的属性(或多或少)是“是一种”的定义,这使得它具有继承性。当你试图用一个句子来描述一个特定的行为时,你会得到类似“我的班级有一只鸭子”的东西,这听起来是错误的,因为如果我的班级“像鸭子一样呱呱叫”,那么当然,“我的班级是一只鸭子”,这使得它是(多重)继承,而不是组合。一年后我读了它,我能把它读成。。“合成行为”=“mixin”(这是继承而不是合成)?