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:
- Distinguish Interface Inheritance from Implementation Inheritance
- Make Interfaces explicit with ABCs (abstract base classes)
- 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?