搞懂 Python 中多繼承與Mixin設計模式

類的單繼承,是我們再熟悉不過的,寫起來也毫不費力。而多繼承呢,見得很多,寫得很少。在很多的項目代碼裏,你還會見到一種很奇怪的類,他們有一個命名上的共同點,就是在類名的結尾,都喜歡用 Mixin。

1. 認識Mixin模式

那我們今天就來講講這個 Mixin,對於這個Mixin,如何理解?它其實是一種設計模式,如果開發者之間沒有產生這樣一種設計模式的共識,那麼設計模式將不復存在。

爲了讓大家,對這個 Mixin 有一個更直觀的理解,我摘錄了網上一段說明。

繼承是一個”is-a”關係。比如轎車類繼承交通工具類,因爲轎車是一個(“is-a”)交通工具。一個物品不可能是多種不同的東西,因此就不應該存在多重繼承。不過有沒有這種情況,一個類的確是需要繼承多個類呢?

答案是有,我們還是拿交通工具來舉例子,民航飛機是一種交通工具,對於土豪們來說直升機也是一種交通工具。對於這兩種交通工具,它們都有一個功能是飛行,但是轎車沒有。所以,我們不可能將飛行功能寫在交通工具這個父類中。但是如果民航飛機和直升機都各自寫自己的飛行方法,又違背了代碼儘可能重用的原則(如果以後飛行工具越來越多,那會出現許多重複代碼)。

怎麼辦,那就只好讓這兩種飛機同時繼承交通工具以及飛行器兩個父類,這樣就出現了多重繼承。這時又違背了繼承必須是”is-a”關係。這個難題該怎麼破?

這時候 Mixin 就閃亮登場了。飛行只是飛機做爲交通工具的一種(增強)屬性,我們可以爲這個飛行的功能單獨定義一個(增強)類,稱之爲 Mixin 類。這個類,是做爲增強功能,添加到子類中的。爲了讓其他開發者,一看就知道這是個 Mixin 類,一般都要求開發者遵循規範,在類名末尾加上 Mixin 。

舉個例子

class Vehicle(object):
    pass

class PlaneMixin(object):
    def fly(self):
        print('I am flying')

class Airplane(Vehicle, PlaneMixin):
    pass

使用Mixin類實現多重繼承要遵循以下幾個規範

  • 責任明確:必須表示某一種功能,而不是某個物品;
  • 功能單一:若有多個功能,那就寫多個Mixin類;
  • 絕對獨立:不能依賴於子類的實現;子類即便沒有繼承這個Mixin類,也照樣可以工作,就是缺少了某個功能。

2. 不使用Mixin的弊端

你肯定會問,不使用 Mixin 行嗎?

當然可以,這個問題就像在問,我不遵循 PEP8 代碼規範行嗎?完全沒問題,只是不推薦那樣做。

那麼到底有什麼理由,讓我們要去用到 Mixin 設計模式呢?

不使用的話,大概有如下三點弊端:

1、結構複雜

單繼承中一個類的父類是什麼,父類的父類是什麼非常明確。多繼承一個類有多個父類,父類又有多個父類,繼承關係複雜。

2、優先順序模糊

多個父類中有同名方法,在開發過程中,容易造成思維混亂,子類不知道繼承哪個父類,會增加開發難度。關於子類的繼承順序,有一個比較複雜的 C3 算法,如果你還不清楚,可以點擊我的另一篇文章 ,瞭解一下。

3、功能衝突

多重繼承有多個父類,但是子類只能繼承一個,對於同名方法,就會導致另一個父類的方法失效。

文末福利

本人原創的 《PyCharm 中文指南》一書前段時間一經發布,就火爆了整個 Python 圈,發佈僅一天的時間,下載量就突破了 1000 ,並且在當天就在 Github 上就收穫了數百的 star,截至目前,下載量已經破萬。

這本書一共將近 200 頁內含大量的圖解製作之精良,值得每個 Python 工程師 人手一份。

爲方便你下載,我將這本書上傳到 百度網盤上了,你可以自行獲取。

鏈接:https://pan.baidu.com/s/1-NzATHFtaTV1MQzek70iUQ

密碼:mft3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章