Python Language
Mixiny
Szukaj…
Składnia
- class ClassName ( MainClass , Mixin1 , Mixin2 , ...): # Używany do deklarowania klasy o nazwie ClassName , main (pierwsza) klasa MainClass i mixiny Mixin1 , Mixin2 itp.
- class ClassName ( Mixin1 , MainClass , Mixin2 , ...): # „Główna” klasa nie musi być pierwszą klasą; naprawdę nie ma różnicy między tym a mixinem
Uwagi
Dodanie mixinu do klasy wygląda bardzo podobnie do dodania nadklasy, ponieważ tak po prostu jest. Obiekt klasy z mieszanym Foo będzie również instancją Foo , a isinstance(instance, Foo)
zwróci true
Mixin
Mixin to zestaw właściwości i metod, które można stosować w różnych klasach, które nie pochodzą z klasy podstawowej. W językach programowania obiektowego zwykle używasz dziedziczenia, aby nadać obiektom różnych klas tę samą funkcjonalność; jeśli zbiór obiektów ma jakąś zdolność, umieścisz ją w klasie podstawowej, z której dziedziczą oba obiekty.
Załóżmy na przykład, że masz klasy
Car
,Boat
iPlane
. Obiekty ze wszystkich tych klas mają zdolność podróżowania, dzięki czemu otrzymują funkcjętravel
. W tym scenariuszu wszyscy podróżują w ten sam podstawowy sposób; wyznaczając trasę i poruszając się nią. Aby zaimplementować tę funkcję, możesz wyprowadzić wszystkie klasy zVehicle
i umieścić tę funkcję we wspólnej klasie: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): ...
Za pomocą tego kodu możesz wywoływać
travel
samochodem (car.travel("Montana")
), statkiem (boat.travel("Hawaii")
) i samolotem (plane.travel("France")
)
Co jednak, jeśli masz funkcjonalność niedostępną dla klasy podstawowej? Załóżmy na przykład, chcesz dać Car
radio i możliwość używania go odtworzyć utwór w radiu, z play_song_on_station
, ale trzeba również Clock
, który można używać radia też. Car
i Clock
mogą dzielić klasę podstawową ( Machine
). Jednak nie wszystkie urządzenia mogą odtwarzać utwory; Boat
i Plane
nie mogą (przynajmniej w tym przykładzie). Jak to zrobić bez powielania kodu? Możesz użyć mixinu. W Pythonie nadanie klasie miksu jest tak proste, jak dodanie go do listy podklas, takich jak to
class Foo(main_super, mixin): ...
Foo
odziedziczy wszystkie właściwości i metody main_super
, ale także właściwości mixin
.
Tak więc, aby dać klasom
Car
i zegar możliwość korzystania z radia, możesz zastąpićCar
z ostatniego przykładu i napisać to: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): ...
Teraz możesz wywoływać
car.play_song_on_station(98.7)
iclock.play_song_on_station(101.3)
, ale nie coś takiego jakboat.play_song_on_station(100.5)
Ważną rzeczą w mixinach jest to, że pozwalają one dodawać funkcjonalność do wielu różnych obiektów, które nie dzielą „głównej” podklasy z tą funkcjonalnością, ale mimo to dzielą dla niej kod. Bez mixin robienie czegoś takiego jak powyższy przykład byłoby znacznie trudniejsze i / lub wymagałoby powtórzenia.
Przesłanianie metod w mieszankach
Mixiny są rodzajem klasy, która służy do „dodawania” dodatkowych właściwości i metod do klasy. Zazwyczaj jest to w porządku, ponieważ wiele razy klasy mixin nie zastępują metod innych lub metod klasy podstawowej. Ale jeśli zastąpisz metody lub właściwości w swoich mixinach, może to prowadzić do nieoczekiwanych wyników, ponieważ w Pythonie hierarchia klas jest definiowana od prawej do lewej.
Na przykład weź następujące klasy
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
W tym przypadku klasa Mixin2 jest klasą podstawową, rozszerzoną o Mixin1 i wreszcie o BaseClass. Dlatego jeśli wykonamy następujący fragment kodu:
>>> x = MyClass()
>>> x.test()
Base
Widzimy, że zwracany wynik pochodzi z klasy Base. Może to prowadzić do nieoczekiwanych błędów w logice kodu i należy to uwzględnić i pamiętać