混入

密新是一組能在不同的類,其使用屬性和方法的來自的基類。在物件導向程式語言中,通常使用繼承為不同類的物件提供相同的功能; 如果一組物件具有某種能力,則將該能力放在兩個物件都繼承的基類中。

例如,假設你有類 CarBoatPlane。來自所有這些類的物件都具有旅行的能力,因此他們獲得了 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)`:
   ...

使用此程式碼,你可以在汽車(car.travel("Montana")),船(boat.travel("Hawaii"))和飛機(plane.travel("France"))上撥打 travel

但是,如果你具有基類不可用的功能,該怎麼辦?比如說,你想給 Car 一個收音機,並且能夠用它來播放一個廣播電臺的歌曲,用 play_song_on_station,但你也有一個可以使用收音機的 ClockCarClock 可以共享一個基類(Machine)。但是,並非所有機器都可以播放歌曲; BoatPlane 不能(至少在這個例子中)。那麼如何在不重複程式碼的情況下完成任務?你可以使用 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,執行類似上述示例的操作會更加困難,並且/或者可能需要重複一些。