A Mixin is a set of properties and methods that can be used in different classes, which don't come from a base class. In Object Oriented Programming languages, you typically use inheritance to give objects of different classes the same functionality; if a set of objects have some ability, you put that ability in a base class that both objects inherit from.
For instance, say you have the classes
Car
,Boat
, andPlane
. Objects from all of these classes have the ability to travel, so they get the functiontravel
. In this scenario, they all travel the same basic way, too; by getting a route, and moving along it. To implement this function, you could derive all of the classes fromVehicle
, and put the function in that shared class:class Vehicle(object): """A generic vehicle class.""" def __init__(self, position): self.position = position def travel(self, destination): route = calculate_route(from=self.position, to=destination) self.move_along(route) class Car(Vehicle): ... class Boat(Vehicle): ... class Plane(Vehicle): ...
With this code, you can call
travel
on a car (car.travel("Montana")
), boat (boat.travel("Hawaii")
), and plane (plane.travel("France")
)
However, what if you have functionality that's not available to a base class? Say, for instance, you want to give Car
a radio and the ability to use it to play a song on a radio station, with play_song_on_station
, but you also have a Clock
that can use a radio too. Car
and Clock
could share a base class (Machine
). However, not all machines can play songs; Boat
and Plane
can't (at least in this example). So how do you accomplish without duplicating code? You can use a mixin. In Python, giving a class a mixin is as simple as adding it to the list of subclasses, like this
class Foo(main_super, mixin): ...
Foo
will inherit all of the properties and methods of main_super
, but also those of mixin
as well.
So, to give the classes
Car
and clock the ability to use a radio, you could overrideCar
from the last example and write this:class RadioUserMixin(object): def __init__(self): self.radio = Radio() def play_song_on_station(self, station): self.radio.set_station(station) self.radio.play_song() class Car(Vehicle, RadioUserMixin): ... class Clock(Vehicle, RadioUserMixin): ...
Now you can call
car.play_song_on_station(98.7)
andclock.play_song_on_station(101.3)
, but not something likeboat.play_song_on_station(100.5)
The important thing with mixins is that they allow you to add functionality to much different objects, that don't share a "main" subclass with this functionality but still share the code for it nonetheless. Without mixins, doing something like the above example would be much harder, and/or might require some repetition.