6

I'm referring to "Fluent Python" by Luciano Ramalho. In chapter 12, there's a section "Coping with Multiple Inheritance" where the author suggests a few best practices, such as:

  1. Distinguish Interface Inheritance from Implementation Inheritance
  2. Make Interfaces explicit with ABCs (abstract base classes)
  3. Use Mixins for Code Reuse

I'll quote:

If a class is designed to provide method implementations for reuse by multiple unrelated subclasses, without implying an “is-a” relationship, it should be an explicit mixin class. Conceptually, a mixin does not define a new type; it merely bundles methods for reuse. A mixin should never be instantiated, and concrete classes should not inherit only from a mixin. Each mixin should provide a single specific behavior, implementing few and very closely related methods.

Emphasis mine. I get the "shouldn't be instantiated" part; it's not meant to be useful on its own. I don't get the "concrete classes should not inherit only from a mixin". Why not? How would that lead to a bad design?

EDIT: Thanks Christophe for your great answer! Allow me to add one little follow-up request for clarification.

So say I have a mixin that cuts down on the boilerplate needed to define overloaded versions for all the various comparison operators:

class TotalOrderMixin:
  """In a class with < and == overloaded, this MixIn implements 
     the other comparisons in terms of those."""

  def __le__(self, other):
    return self < other or self == other

  def __ge__(self, other):
    return not self < other

  def __gt__(self, other):
    return not self <= other

  ...

Then going by the author's advice, I should not inherit from TotalOrderMixin in a concrete class. Rather, I should first define an abstract class:

class MinimumOrder(ABC):
  @abstractmethod
  def __lt__(self, other):
    """self is strictly smaller than other"""
  
  @abstractmethod
  def __eq__(self, other):
    ""test for equality"""

And then we compose this ABC with the mixin:

class TotalOrderABC(MinimumOrderABC, TotalOrderMixin):
  pass

and then our concrete class may inherit from that ABC?

2
  • 4
    I didn't read the book, and I can only guess the intended meaning, but, if you accept that a mixin is "not meant to be useful on its own", and couple that with the recommendation (2.) to make interfaces explicit, then a class that only inherits from a mixin (and has no ABC) might end up just being a utility class that provides a number of methods, but that's something that the mixin already does. Commented Jan 1, 2021 at 5:49
  • It's probably intended as more of a general rule, a design smell to look out for. If your class provides some actual behavior and exposes its own methods to model some business concept, and just makes use of the mixin "internally", that's probably OK, but might not be aligned well with the author's overall design philosophy. Commented Jan 1, 2021 at 5:49

1 Answer 1

5

Mixins are a way to compose functionality at the level of classes instead of using object composition. The idea is to have a base class and enrich it by combining it with reusable mixins using multiple inheritance.

Since mixins do not really define a type, you should not instantiate them. You already got this.

The usual way is therefore to have an independent base class and create derived classes that inherits the base class and one or several mixins.

You could of course imagine a concrete base class (i.e. meant to be instantiated) for your own type that already inherits from a mixin. But this is not advised because:

  • Your base class is coupled to a mixin. This breaks the idea of having the mixin used by multiple unrelated classes.
  • A class inheriting only from a single mixin could be understood as a specialisation of that mixin (OO semantic of inheritance). The expectation would hence be that it is not instantiated directly. This kind of construct is therefore a source of ambiguity.

This is why the author suggests this “best practice”. (Unrelated to your question: personally, despite having heavily used multiple inheritance, I still prefer composition over inheritance and find the mixin gymnastics quite challenging, if not counterintuitive in view of OO inheritance semantics)

2
  • Thank you very much for the great answer. I added one concrete example to my question to see if I understand correctly. If you could comment on that, I'd much appreciate it!
    – Lagerbaer
    Commented Jan 4, 2021 at 16:20
  • @Lagerbaer your example is exactly the idea ! I think you understood correctly :-)
    – Christophe
    Commented Jan 4, 2021 at 16:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.