混入

密新是一组能在不同的类,其使用属性和方法的来自的基类。在面向对象编程语言中,通常使用继承为不同类的对象提供相同的功能; 如果一组对象具有某种能力,则将该能力放在两个对象都继承的基类中。

例如,假设你有类 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,执行类似上述示例的操作会更加困难,并且/或者可能需要重复一些。