banner
Rick Sanchez

Rick Sanchez

OS && DB 爱好者,深度学习炼丹师,蒟蒻退役Acmer,二刺螈。

Mixin design pattern in Python

image

1. What is the Mixin Design Pattern#

The mixin design pattern can be seen as a form of multiple inheritance. So first, let's talk about why this kind of syntax of multiple inheritance exists.

Cars and airplanes both belong to the category of transportation, but airplanes can fly, while cars cannot. Therefore, the behavior of flying cannot be written in the class of transportation. If each transportation implements its own method of travel, it violates the principle of reusing code as much as possible (if there are more and more types of transportation, it will cause a lot of code redundancy).

Therefore, in order to represent the behavior of flying, we need to use multiple inheritance. But in doing so, we violate the principle that inheritance relationships must be based on the "is-a" principle.

In Java, although there is no multiple inheritance, we can achieve multiple inheritance through interface.

In Python, there is no syntax for interface, but it supports multiple inheritance itself.

When using multiple inheritance, it is easy to design improperly, resulting in a messy inheritance chain and affecting the mro lookup. Therefore, our principle in programming is to use other methods instead of multiple inheritance as much as possible.

At this time, the Mixin design pattern comes into play. The direct translation of Mixin is "mix-in" or "supplement", which is a form of multiple inheritance. In multiple inheritance, the search order is based on the order of the mro inheritance chain.


2. Example of Mixin Design Pattern#

class Vehicle:
    pass

class PlaneMixin:
    def fly(self):
        print("Flying")

class Airplane(Vehicle, PlaneMixin):
    pass

As can be seen from the above code, the Airplane class implements multiple inheritance. In the inheritance chain, it inherits the Vehicle class and the PlaneMixin class. Here we follow the requirements of the Mixin design pattern and add the suffix Mixin to enhance the readability of the code.

The above code can be understood as follows: Airplane is just a Vehicle class, not a Plane class, and the Mixin suffix tells other readers that this class is added as a function to the subclass, not as a parent class. Its role is equivalent to interface in Java.

In this way, we don't need a complex and large inheritance chain. We only need to choose the functionality of different classes to quickly construct the desired subclass.


3. Principles of Using the Mixin Design Pattern#

When using the Mixin design pattern to achieve multiple inheritance, pay special attention to the following principles:

  • First, the Mixin class must represent a certain functionality, not an object, which is the same as Runnable and Callable in Java.
  • Secondly, it should have a single responsibility, if there are multiple functionalities, we should implement multiple Mixin classes.
  • Next, the Mixin class does not depend on the implementation of the subclass and belongs to an abstract class. It cannot be instantiated itself and cannot inherit classes other than Mixin.
  • Finally, even if the subclass does not inherit the Mixin class, it must still work properly, only some functionality is missing and cannot be used.

Java interfaces only provide "specifications" for multiple inheritance. Mixin classes provide both "specifications" and "implementations" for multiple inheritance, making them easier to use than interfaces.


4. Supplement#

In other frameworks or languages, there are also similar Mixin features, such as Ruby, Django, Vue, React, and so on.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.