Классы-примеси (mixin) в Python

Mixin представляет собой набор свойств и методов , которые могут быть использованы в различных классах, которые не приходят из базового класса. В объектно - ориентированных языках программирования, вы , как правило , использовать наследование , чтобы дать объекты различных классов ту же функциональность; если множество объектов есть некоторые способности, вы помещаете эту способность в базовом классе , что оба объекта унаследованы из.

Однако что если у вас есть функциональность, недоступная базовому классу? Скажем, к примеру, вы хотите , чтобы Car радио и возможность использовать его , чтобы играть песню на радиостанции, с play_song_on_station , но у вас также есть Clock , которые могут использовать радио тоже. Car и Clock могут совместно использовать базовый класс ( Machine ). Однако не все машины могут воспроизводить песни; Boat и Plane не может ( по крайней мере , в данном примере). Так как же добиться успеха без дублирования кода? Вы можете использовать миксин. В Python дать классу mixin так же просто, как добавить его в список подклассов, как это

class Foo(main_super, mixin): ... 

Foo наследует все свойства и методы main_super , но и те из mixin , а также.

Таким образом, чтобы дать классы для Car и Часовой возможность использовать радио, вы можете переопределить Car из предыдущего примера и написать это:

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):
   ... 

Теперь вы можете вызвать car.play_song_on_station(98.7) и clock.play_song_on_station(101.3) , но не что - то вроде boat.play_song_on_station(100.5)

С миксинами важно то, что они позволяют вам добавлять функциональные возможности к разным объектам, которые не разделяют «основной» подкласс с этой функциональностью, но, тем не менее, совместно используют код для него. Без миксинов сделать что-то похожее на приведенный выше пример будет гораздо сложнее и / или может потребоваться некоторое повторение.

Переопределение методов в миксинах

Mixins - это своего рода класс, который используется для «добавления» дополнительных свойств и методов в класс. Это обычно хорошо, потому что много раз классы mixin не переопределяют методы друг друга или базового класса. Но если вы переопределите методы или свойства в своих миксинах, это может привести к неожиданным результатам, потому что в Python иерархия классов определяется справа налево.

Например, возьмите следующие классы

class Mixin1(object):
    def test(self):
        print "Mixin1"

class Mixin2(object):
    def test(self):
        print "Mixin2"

class BaseClass(object):
    def test(self):
        print "Base"

class MyClass(BaseClass, Mixin1, Mixin2):
    pass

 

В этом случае класс Mixin2 является базовым классом, расширенным с помощью Mixin1 и, наконец, с помощью BaseClass. Таким образом, если мы выполним следующий фрагмент кода:

>>> x = MyClass()
>>> x.test()
Base

Мы видим возвращаемый результат из базового класса. Это может привести к непредвиденным ошибкам в логике вашего кода и должно учитываться и учитываться