繼承 (inheritance) 是物件導向程式設計 (object-oriented programming) 的主要特性之一,讓類別 (class) 設計可以有共通屬性 (attribute) 及共通方法 (method) ,這些共通的部分是在父類別 (superclass) 定義,子類別 (subclass) 繼承父類別之後就取得父類別的屬性及方法,子類別還可以定義自己專用的屬性及方法。
繼承的英文動詞原文為 inherit ,意思泛指從什麼得到什麼,中文意思除了繼承外,遺傳上也是用這個詞,就物件導向程式設計而言,意思比較接近遺傳,也就是子類別從父類別得到屬性及方法,子類別與父類別仍會同時存在,
然而繼承中文的原本意思是指先人去世,後人繼承先人的財產、精神等等,程式設計中卻沒有這種意味,因此需要特別留意,此外由於繼承是很久以前的翻譯用詞,也已經變成物件導向程式設計中的慣用詞,因此我們仍然是沿用繼承一詞。
繼承的寫法很簡單,這裡 Demo 當作父類別, Demo2 為子類別,就在 Demo2 的識別字 (identifier) 後面加上小括弧,小括弧中寫上要繼承的父類別名稱,這樣 Demo2 就繼承了 Demo
class Demo:
pass
class Demo2(Demo):
pass
#《程式語言教學誌》的範例程式
# http://kaiching.org/
# 檔名:inherit01.py
# 功能:示範定義類別
# 作者:張凱慶
內建函數 (built-in function) isinstance() 可用來判斷變數 (variable) 是否為某類別的實體 (instance) 物件 (object) ,第一個參數為變數名稱,第二個參數為類別名稱,這裡由於變數 d 就是 Demo 的實體物件,因此回傳 True 。另一個內建函數 issubclass() 則是判斷第一個參數是否為第二個參數的子類別,由於此例 Demo2 為 Demo 的子類別,因此回傳 True
from inherit01 import Demo
from inherit01 import Demo2
d = Demo()
print(isinstance(d, Demo))
print(issubclass(Demo2, Demo))
#《程式語言教學誌》的範例程式
# http://kaiching.org/
# 檔名:inherit02.py
# 功能:示範定義類別
# 作者:張凱慶
於命令列執行以上程式,結果如下
$ python3 inherit02.py |
True |
True |
$ |
這裡看到 Demo4 繼承 Demo3 ,類別屬性 (class attribute) i 及實體屬性 (instance attribute) j 都會被繼承
class Demo3:
i = 0
def __init__(self):
self.j = 0
Demo3.i += 1
class Demo4(Demo3):
pass
d1 = Demo3()
print(d1.i, d1.j)
d2 = Demo4()
print(d2.i, d2.j)
#《程式語言教學誌》的範例程式
# http://kaiching.org/
# 檔名:inherit03.py
# 功能:示範定義類別
# 作者:張凱慶
於命令列執行以上程式,結果如下
$ python3 inherit03.py |
1 0 |
2 0 |
$ |
這裡 Demo5 同樣繼承 Demo3 ,由於 Demo5 改寫 (override) 了 __init__() 方法,因此實體屬性 j 並沒有被繼承
from inherit03 import Demo3
class Demo5(Demo3):
def __init__(self):
self.k = 0
d3 = Demo5()
print(d3.i, d3.j, d3.k)
#《程式語言教學誌》的範例程式
# http://kaiching.org/
# 檔名:inherit04.py
# 功能:示範定義類別
# 作者:張凱慶
於命令列執行以上程式,結果如下
$ python3 inherit04.py |
1 0 |
2 0 |
Traceback (most recent call last): |
File "inherit04.py", line 8, in <module> |
print(d3.i, d3.j, d3.k) |
AttributeError: 'Demo5' object has no attribute 'j' |
$ |
如果改寫過的 __init__() 方法要繼承原有的實體屬性,就要用內建函數 super() 先呼叫父類別的 __init__() 方法,例如這裡 Demo6 的 __init__() 方法就先用 super() 呼叫,因此實體屬性 j 就被繼承到 Demo6 中了
from inherit03 import Demo3
class Demo6(Demo3):
def __init__(self):
super().__init__()
self.k = 0
d4 = Demo6()
print(d4.i, d4.j, d4.k)
#《程式語言教學誌》的範例程式
# http://kaiching.org/
# 檔名:inherit05.py
# 功能:示範定義類別
# 作者:張凱慶
於命令列執行以上程式,結果如下
$ python3 inherit05.py |
1 0 |
2 0 |
3 0 0 |
$ |
相關教學影片