目標
- 單繼承
- 多繼承
面向對象三大特性
- 封裝 根據 職責 將 屬性 和 方法 封裝 到一個抽象的 類 中
- 繼承 實現代碼的重用,相同的代碼不需要重複的編寫
- 多態 不同的對象調用相同的方法,產生不同的執行結果,增加代碼的靈活度
01. 單繼承
1.1 繼承的概念、語法和特點
繼承的概念:子類 擁有 父類 的所有 方法 和 屬性
1) 繼承的語法
class 類名(父類名):
pass
- 子類 繼承自 父類,可以直接 享受 父類中已經封裝好的方法,不需要再次開發
- 子類 中應該根據 職責,封裝 子類特有的 屬性和方法
2) 專業術語
Dog
類是Animal
類的子類,Animal
類是Dog
類的父類,Dog
類從Animal
類繼承Dog
類是Animal
類的派生類,Animal
類是Dog
類的基類,Dog
類從Animal
類派生
3) 繼承的傳遞性
C
類從B
類繼承,B
類又從A
類繼承- 那麼
C
類就具有B
類和A
類的所有屬性和方法
子類 擁有 父類 以及 父類的父類 中封裝的所有 屬性 和 方法
1.2 方法的重寫
- 子類 擁有 父類 的所有 方法 和 屬性
- 子類 繼承自 父類,可以直接 享受 父類中已經封裝好的方法,不需要再次開發
應用場景
- 當 父類 的方法實現不能滿足子類需求時,可以對方法進行 重寫(override)
重寫 父類方法有兩種情況:
- 覆蓋 父類的方法
- 對父類方法進行 擴展
1) 覆蓋父類的方法
- 如果在開發中,父類的方法實現 和 子類的方法實現,完全不同
- 就可以使用 覆蓋 的方式,在子類中 重新編寫 父類的方法實現
具體的實現方式,就相當於在 子類中 定義了一個 和父類同名的方法並且實現
重寫之後,在運行時,只會調用 子類中重寫的方法,而不再會調用 父類封裝的方法
2) 對父類方法進行 擴展
- 如果在開發中,子類的方法實現 中 包含 父類的方法實現
- 父類原本封裝的方法實現 是 子類方法的一部分
- 就可以使用 擴展 的方式
- 在子類中 重寫 父類的方法
- 在需要的位置使用
super().父類方法
來調用父類方法的執行 - 代碼其他的位置針對子類的需求,編寫 子類特有的代碼實現
關於 super
- 在
Python
中super
是一個 特殊的類 super()
就是使用super
類創建出來的對象- 最常 使用的場景就是在 重寫父類方法時,調用 在父類中封裝的方法實現
調用父類方法的另外一種方式(知道)
在
Python 2.x
時,如果需要調用父類的方法,還可以使用以下方式:
父類名.方法(self)
- 這種方式,目前在
Python 3.x
還支持這種方式 - 這種方法 不推薦使用,因爲一旦 父類發生變化,方法調用位置的 類名 同樣需要修改
提示
- 在開發時,
父類名
和super()
兩種方式不要混用 - 如果使用 當前子類名 調用方法,會形成遞歸調用,出現死循環
- 私有屬性、方法 是對象的隱私,不對外公開,外界 以及 子類 都不能直接訪問
- 私有屬性、方法 通常用於做一些內部的事情
示例
B
的對象不能直接訪問__num2
屬性B
的對象不能在demo
方法內訪問__num2
屬性B
的對象可以在demo
方法內,調用父類的test
方法- 父類的
test
方法內部,能夠訪問__num2
屬性和__test
方法
02. 多繼承
概念
- 子類 可以擁有 多個父類,並且具有 所有父類 的 屬性 和 方法
- 例如:孩子 會繼承自己 父親 和 母親 的 特性
語法
class 子類名(父類名1, 父類名2...)
pass
2.1 多繼承的使用注意事項
問題的提出
- 如果 不同的父類 中存在 同名的方法,子類對象 在調用方法時,會調用 哪一個父類中的方法呢?
提示:開發時,應該儘量避免這種容易產生混淆的情況! —— 如果 父類之間 存在 同名的屬性或者方法,應該 儘量避免 使用多繼承
Python 中的 MRO —— 方法搜索順序(知道)
Python
中針對 類 提供了一個 內置屬性__mro__
可以查看 方法 搜索順序- MRO 是
method resolution order
,主要用於 在多繼承時判斷 方法、屬性 的調用 路徑
print(C.__mro__)
輸出結果
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
- 在搜索方法時,是按照
__mro__
的輸出結果 從左至右 的順序查找的 - 如果在當前類中 找到方法,就直接執行,不再搜索
- 如果 沒有找到,就查找下一個類 中是否有對應的方法,如果找到,就直接執行,不再搜索
- 如果找到最後一個類,還沒有找到方法,程序報錯
新式類與舊式(經典)類
object
是Python
爲所有對象提供的基類
,提供有一些內置的屬性和方法,可以使用dir
函數查看
-
新式類:以
object
爲基類的類,推薦使用 -
經典類:不以
object
爲基類的類,不推薦使用 -
在
Python 3.x
中定義類時,如果沒有指定父類,會 默認使用object
作爲該類的 基類 ——Python 3.x
中定義的類都是 新式類 -
在
Python 2.x
中定義類時,如果沒有指定父類,則不會以object
作爲 基類
新式類 和 經典類 在多繼承時 —— 會影響到方法的搜索順序
爲了保證編寫的代碼能夠同時在 Python 2.x
和 Python 3.x
運行!
今後在定義類時,如果沒有父類,建議統一繼承自 object
class 類名(object):
pass