爲何要用mix-in混合類
Python是面向對象的編程語言,它提供了一些內置的編程機制,使得開發者能夠適當地實現多重繼承,即一個子類能夠繼承多個父類,可是多重繼承的設計常常被人詬病,由於它違背了「is-a」的關係。可是也存在須要多重繼承的狀況。python
例如,轎車是一個交通工具,因此轎車類應該繼承交通工具這個父類。那民航飛機呢?它也屬於交通工具的一種,因此也應該繼承交通工具這個父類,可是交通工具這個類應該怎麼設計?是否應該實現飛行功能?若是實現,那轎車繼承交通工具父類顯然不合適,由於轎車根本沒有飛行功能。若是不實現,民航飛機繼承交通工具類也一樣不合適。若是二者都分別實現本身的方法,那將會違背代碼重用的原則,那應該這麼解決這個問題?事實上,咱們能夠把地上跑的,天上飛的,甚至水上漂的這些工具的功能抽象出來實現交通工具這個父類。對於飛機來講,那就去繼承交通工具和有飛行功能兩個父類,對於船來講,那就去繼承交通工具和有水上漂功能的兩個父類。可是這樣子的多重繼承說到底仍是違背了「is-a」的原則,這個問題應該怎麼樣處理?編程
其實在Python裏,是能夠這樣子處理的,看示例1。編程語言
#示例1 class Vehicle(object): def move(self): print("I can move on the road") class FlyMixin(object): def fly(self): print("I can fly in the sky") class Airplane(Vehicle, FlyMixin): pass
在示例1中,Airplane繼承了Vehicle和PlaneMixin兩個類,這是多重繼承嗎?其實能夠說是,也能夠說不是。由於從語法上來講,的確是多重繼承。不過要注意的是Airplane第二個繼承的是類名稱有「mixin」,說明這是一個混合類(mix-in類),它會告訴讀代碼的人,這個FlyMixin類只是起到一個輔佐做用,它只是把某一個功能添加到類中,即便沒有繼承這個FlyMixin類也沒有影響。mix-in是一個小型的類,它只是定義了其餘類可能須要的一套附加方法,而不定義本身實例屬性,此外,它也不要求使用者調用本身的構造器。工具
瞭解完mix-in類,咱們一塊兒來看看示例2的例子。設計
#示例2 class Animal(object): def run(self): print("I can run!") def eat(self): print("I can eat!") def drink(self): print("I can drink") def sleep(self): print("I can sleep") class AnimalMixin(object): def maketools(self): print("I can make tools!") class Person(Animal, AnimalMixin): def superpower(self): super().maketools() Jack = Person() Jack.superpower() #輸出結果:I can make tools!
人和其餘動物都具備run,eat,drink,sleep方法,可是人和其餘動物的區別是人能夠製造工具。因此咱們在mix-in類中實現maketools方法,它用於給Person類添加一個額外功能咱們在實現Person類的時候,繼承了Animal父類和AnimalMixin混合類。繼承的UML圖以下圖所示:code
說到多重繼承,不得不說一下方法順序解釋(MRO),當子類調用super()放時候,它指明瞭查找方法的順序。對象
print(Person.__mro__) #輸出結果: # (<class '__main__.Person'>, <class '__main__.Animal'>, <class '__main__.AnimalMixin'>, <class 'object'>)
super()查找順序以下圖所示(虛線)。繼承
混合類應該要注意
- 它應該表示某一種功能。
- 它必須負責單一的功能,若是須要多功能,請實現多個Mix-in類。
- 不依賴子類的實現。
- 子類即便沒有實現Mix-in類,也能夠正常工做,只是少了一個功能罷了。
公衆號: CVpython開發
專一於分享Python和計算機視覺,咱們堅持原創,不按期更新,但願咱們的文章能夠啓發到你,一塊兒進步。快點掃碼關注我吧。class