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. Это может привести к непредвиденным ошибкам в логике вашего кода, и их необходимо учитывать и учитывать