Python Language
Примеси
Поиск…
Синтаксис
- class ClassName ( MainClass , Mixin1 , Mixin2 , ...): # Используется для объявления класса с именем ClassName , основным (первым) классом MainClass и mixins Mixin1 , Mixin2 и т. д.
- class ClassName ( Mixin1 , MainClass , Mixin2 , ...): # «Основной» класс не должен быть первым классом; нет никакой разницы между ним и mixin
замечания
Добавление mixin в класс очень похоже на добавление суперкласса, потому что это в значительной степени именно это. Объект класса с mixin Foo также будет экземпляром Foo , а isinstance(instance, Foo)
вернет true
Mixin
Mixin - это набор свойств и методов, которые могут использоваться в разных классах, которые не относятся к базовому классу. В языках объектно-ориентированного программирования вы обычно используете наследование для предоставления одинаковым функциям объектов разных классов; если набор объектов обладает некоторой способностью, вы помещаете эту способность в базовый класс, на который оба объекта наследуются .
Например, скажем, у вас есть классы
Car
,Boat
иPlane
. Объекты из всех этих классов имеют возможность путешествовать, поэтому они получают функциюtravel
. В этом сценарии все они перемещаются одним и тем же основным способом; путем получения маршрута и перемещения по нему. Чтобы реализовать эту функцию, вы можете получить все классы изVehicle
и поместить функцию в этот общий класс: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): ...
С помощью этого кода вы можете позвонить в
travel
по машине (car.travel("Montana")
), лодку (boat.travel("Hawaii")
) и самолет (plane.travel("France")
)
Однако, что, если у вас есть функциональность, недоступная базовому классу? Скажем, например, вы хотите дать Car
радио и возможность использовать его для воспроизведения песни на радиостанции с помощью play_song_on_station
, но у вас также есть Clock
которые также могут использовать радио. Car
и Clock
могут делиться базовым классом ( Machine
). Однако не все машины могут воспроизводить песни; Boat
и Plane
не могут (по крайней мере, в этом примере). Итак, как вы это делаете без дублирования кода? Вы можете использовать mixin. В 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 заключается в том, что они позволяют добавлять функциональные возможности к различным объектам, которые не разделяют «основной» подкласс с этой функциональностью, но тем не менее все равно используют код для него. Без миксинов делать что-то вроде приведенного выше примера было бы намного сложнее и / или потребовало бы повторения.
Переопределение методов в миксинах
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
Мы видим, что результат возвращается из класса Base. Это может привести к непредвиденным ошибкам в логике вашего кода, и их необходимо учитывать и учитывать