在Python中,mixins是否相当于组合?如果是这样,为什么不只是使用组合?

时间:2013-07-13 12:23:57

标签: python inheritance mixins composition

我理解mixin看起来像继承,但更像是组合 (编辑:我倾向于通过mixin而不是giving additional functionality/attributes来考虑giving another is-a relationship。)
在心理上,当我使用mixin时,我说的是这样的东西:我给你的是你缺少的混合物,而不是你实际上也是这种混合型。(is-a)

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

我们可以使用直接的成分而不是mixins,什么是mixin?

如果我不得不猜测,那是因为my_instance.foo()比my_instance.another_instance.foo()更容易吗? (如果mixin有foo(),你可以使用my_instance.foo(),当你将another_instance复合为my_instance的属性时,你需要my_instance.another_instance.foo())

还有其他原因吗?


编辑:

所以即使我觉得它有 - a,mixin仍然是一种关系。当你使用is-a时,你得到的好处是更清洁的界面。那就是我如何理解德尔南的答案。

1 个答案:

答案 0 :(得分:8)

  

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

错了,它确实给你一个is-a关系。考虑class C(A, B)issubclass(C, A)是真的,issubclass(C, B)也是如此。调用C().method_of_B()调用B的方法,如果它没有被覆盖在MRO中的某个地方(也可能发生单继承!),同样适用于A的方法。属性访问C().attr_of_{a,b}也为您提供了AB的属性(与方法相同的警告)。

  

我读过几次,你应该更喜欢作文而不是继承。

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

  • A是一种关系是错误的,例如因为它违反了Liskov替代原则。这个原因不受mixins的影响,见上文。
  • 由于各种原因,组合物更容易或更不容易出错。这个原因在mixin可能的情况下也是有效的,如果它被放大了,因为它可能有点棘手(though not impossible)来使MRO和super()调用序列正确。
  

如果我不得不猜测,那是因为my_instance.foo()比my_instance.another_instance.foo()更容易?

这只是一些额外的角色。更重要的是,您必须为要重新导出的每个方法重新键入包装器方法(如果您通过组合模拟is-a关系,那么它们将所有 )。

从概念上讲,如果C确实是A,那么这个手动工作似乎毫无意义且容易出错。 Mixins / multiple inheritance支持一个对象超过单个bass类可以或应该表示的对象的情况。例如,UTF-8字符串可以是ByteBufferUnicodeStream。一般来说,我们有这样的接口(或者没有;在Python中这是隐式的),但mixins还允许以可组合和方便的方式添加相关的功能。