子類別也可依需要改寫 (override) 父類別的方法,這是說子類別需要用到與父類別具有相同名稱的方法,但是子類別需要的功能有所修改、擴充或增加,因此當子類別裡頭定義與父類別相同名稱的方法時,就會改寫父類別的方法。經過改寫,子類別的方法完全屬於子類別所有,例如以下程式
class Demo:
__x = 0
def __init__(self, i):
self.__i = i
Demo.__x += 1
def __str__(self):
return str(self.__i)
def hello(self):
print("hello " + self.__str__())
@classmethod
def getX(cls):
return cls.__x
class SubDemo(Demo):
def __init__(self, i, j):
self.__i = i
self.__j = j
def __str__(self):
return str(self.__i) + "+" + str(self.__j)
a = SubDemo(1234)
a.hello()
print("a.__x =", a.getX())
b = SubDemo(56, 78)
b.hello()
print("b.__x =", b.getX())
print()
print("a.__x =", a.getX())
print("b.__x =", b.getX())
# 《程式語言教學誌》的範例程式
# http://pydoing.blogspot.com/
# 檔名:cla19.py
# 功能:示範 Python 程式
# 作者:張凱慶
# 時間:西元 2010 年 12 月 執行結果如下

Demo 為父類別,定義四個方法, SubDemo 為子類別,改寫 Demo 的兩個方法,包括 __init__() 與 __str__() 。
我們可以發現, Demo 有個 __x 變數,原本用來算有多少 Demo 實體 (instance) 被建立,我們想這應該要包括子類別 SubDemo 的實體數量,也就是說, __x 應該等於 Demo 實體總數加上 SubDemo 實體總數。此例中我們建立兩個 SubDemo 實體,可是 __x 卻等於 0 。
這是為什麼呢?因為此例中 Demo 的 __init__() 方法從頭到尾沒有被呼叫過,因此 __x 始終保持為初值 0 。解決這個問題的方法很簡單,一個幾單的途徑是在子類別 SubDemo 新增一個 __x ,但是這樣一來就只能累計 SubDemo 的實體數量,若是還有其他子類別繼承自 Demo ,這就無法一同列入計算了。
另一個解決途徑是在子類別改寫的方法中先呼叫 (call) 父類別的方法,這可利用內建函數 (function) super() ,如下
class Demo:
__x = 0
def __init__(self, i):
self.__i = i
Demo.__x += 1
def __str__(self):
return str(self.__i)
def hello(self):
print("hello " + self.__str__())
@classmethod
def getX(cls):
return cls.__x
class SubDemo(Demo):
def __init__(self, i, j):
super().__init__(i)
self.__j = j
def __str__(self):
return super().__str__() + "+" + str(self.__j)
a = SubDemo(12, 34)
a.hello()
print("a.__x =", a.getX())
b = SubDemo(56, 78)
b.hello()
print("b.__x =", b.getX())
print()
print("a.__x =", a.getX())
print("b.__x =", b.getX())
# 《程式語言教學誌》的範例程式
# http://pydoing.blogspot.com/
# 檔名:cla20.py
# 功能:示範 Python 程式
# 作者:張凱慶
# 時間:西元 2010 年 12 月 執行結果如下

第 19 行到第 21 行
def __init__(self, i, j):
super().__init__(i)
self.__j = jSubDemo 的 __init__() 定義中,我們利用 super() 呼叫父類別 Demo 的 __init__() ,因此需提供 i 當作參數 (parameter) 。注意,這裡 self.__i 變成父類別的私有屬性。
第 23 行到第 24 行
def __str__(self):
return super().__str__() + "+" + str(self.__j)這裡的 __str__() ,在 return 後的運算式 (expression) 先呼叫 super().__str__() ,因為 self.__i 已經變成父類別 Demo 私有屬性,因此需要先呼叫父類別的 __str__() 。
| 中英文術語對照 | |
|---|---|
| 子類別 | subclass |
| 屬性 | attribute |
| 方法 | method |
| 父類別 | superclass |
| 繼承 | inherit |
| 改寫 | override |
| 實體 | instance |
| 呼叫 | call |
| 函數 | function |
| 參數 | parameter |
| 運算式 | expression |
參考資料
http://docs.python.org/py3k/tutorial/classes.html
http://docs.python.org/py3k/reference/compound_stmts.html
http://docs.python.org/py3k/tutorial/classes.html
http://docs.python.org/py3k/reference/compound_stmts.html
1 則留言:
在第一個範例裡
a = SubDemo(1234)應該會報錯
因為找不到只吃一個引數的SubDemo建構子
張貼留言