9

I understand mixin as what looks like inheritance but what is more like composition.
(edit: I tend to think giving additional functionality/attributes by mixin rather than giving another is-a relationship.)
Mentally, I'm saying something like this when I use mixin: I'm giving you this mixin you are missing, rather than you are actually this mixin-type as well.(is-a)

And I read few times, you should prefer composition over inheritance.

We could just use straight compositions instead of mixins, what is mixin for?

If I have to guess, it's because my_instance.foo() is easier than my_instance.another_instance.foo()?
(You can use my_instance.foo() if mixin has foo(), you need my_instance.another_instance.foo() when you composite another_instance as an attribute of my_instance)

Are there any other reason?


Edit:

So even though I feel it's has-a, mixin is still is-a relationship. and benefit you get when you use is-a here is, cleaner interface. That' how I interpret delnan's answer.

mt3
  • 2,654
  • 4
  • 26
  • 29
eugene
  • 39,839
  • 68
  • 255
  • 489
  • Mixin is just a different name for multiple inheritance, not for composition. Actually you should say "sensible multiple inheritance" since mixin classes are *designed* to be used with multiple inheritance. I don't really see where mixin provide an has-a relationship vs is-a. By the way: using `__getattr__` it's trivial to be able to do `my_instance.foo()` instead of `my_instance.another_instance.foo()` (and please, note that for PEP8 instance attributes should have `names_with_lowercase_with_underscores`, not `semiCamelCase`) – Bakuriu Jul 13 '13 at 12:58

1 Answers1

11

(Since mixin doesn't give you is-a relationship, it gives you has-a)

Wrong, it does give you a is-a relationship. Consider class C(A, B). issubclass(C, A) is true and so is issubclass(C, B). The call C().method_of_B() calls the method of B if it isn't overridden somewhere in the MRO (which can happen with single inheritance too!), and similarly for methods of A. The attribute access C().attr_of_{a,b} gives you an attribute of A or B too (same caveat as with methods).

And I read few times, you should prefer composition over inheritance.

This rule of thumb exists because many people tend to use inheritance where it isn't appropriate, not because inheritance isn't a useful tool in any case. This applies to Python too. Common (good) reasons include:

  • A is-a relationship would be wrong, for example because it breaks the Liskov Substitution Principle. This reason is not affected by mixins, see above.
  • Composition is easier or less error-prone, for various reasons. This reason is valid when mixins are possible too, if anything it's amplified as it can be a bit tricky (though not impossible) to get the MRO and sequence of super() calls right.

If I have to guess, it's because my_instance.foo() is easier than my_instance.another_instance.foo()?

That's just a few additional characters. More important is that you have to re-type wrapper methods for every single method you want to re-export (which would be all of them if you're emulating an is-a relationship via composition).

More conceptually, this manual work seems pointless and error-prone if C really is-a A. Mixins/multiple inheritance support the case where an object is more than what can or should be represented by a single bass class. For example, a UTF-8 string may be both a ByteBuffer and a UnicodeStream. In general, we have interfaces for this (or not; in Python this is implicit), but mixins also allow adding related functionality in a composable and convenient manner.

  • 1
    `Wrong, it does give you a is-a relationship.` OK. I didn't write it clearly. Let me rephrase: Mixin feels more like has-a instead of is-a because it gives a functionality which an original class misses. – eugene Jul 13 '13 at 19:52
  • @eugene I think I see where you're coming from, but I don't think that's a useful way to think about it. There is no one "original class". There are a couple of base classes, and the derived class inherits some bits from each of the base classes. –  Jul 13 '13 at 20:03
  • What can be misleading, is if you think "my class *has a* behavior", and based on the words "has a", you mistakenly think you're using composition. The property of having a behavior is (more or less) the definition of "is a", which makes it inheritance. When you try formulating a sentence to describe a *specific* behavior, you get something like "my class *has a* duck", which sounds wrong, because it is - if my class "quacks like a duck", then of course, "my class *is a* duck", which makes it (multiple) inheritance, not composition. – mindplay.dk Jan 17 '14 at 01:47
  • now I read it after a year after, Can I read it as.. "compositing behavior" = "mixin" (and it is inheritance not composition) ? – eugene Jan 14 '15 at 02:01