Photo by David Travis on Unsplash
今天要來介紹的Python繼承(Inheritance)在物件導向設計中非常的重要,使用得當可以提高我們程式碼的重用性(Reusable)及維護性。
繼承(Inheritance)顧名思義,就是會有父類別(或稱基底類別Base Class)及子類別(Sub Class)的階層關係。子類別會擁有父類別公開的屬性(Attribute)及方法(Method)。
所以Python繼承(Inheritance)的概念就是將各類別(Class)會共同使用的屬性(Attribute)或方法(Method)放在一個獨立的類別(Class)中,其它的類別(Class)透過繼承(Inheritance)的方式來擁有,降低程式碼的重複性。
Python繼承(Inheritance)的重要觀念如下:
- 如何使用Python繼承(Inheritance)
- 方法覆寫(Method Overriding)
- 多層繼承(Multi-Level Inheritance)
- 多重繼承(Multiple Inheritance)
一、如何使用Python繼承(Inheritance)
在實務上開發應用程式時,隨著類別(Class)的增加,可能會發現有些類別(Class)擁有共同的屬性(Attribute)或方法(Method),如下範例:
# 汽車類別
class Car:
# 駕駛方法
def drive(self):
print("drive method is called.")
# 加速方法
def accelerate(self):
print("accelerate method is called.")
# 飛機類別
class Airplane:
# 駕駛方法
def drive(self):
print("drive method is called.")
# 飛行方法
def fly(self):
print("fly method is called.")
範例中的Car及Airplane類別(Class)皆擁有drive()方法,當其有數百行程式碼時,在應用程式中重複出現是不好的且違背DRY(Don't Repeat Yourself)原則,未來這個方法(Method)有問題或邏輯改變了,就要修改好幾個地方,難於維護。
這時候就可以使用物件導向的繼承(Inheritance)設計,將共同的屬性(Attribute)或方法(Method)定義在一個類別(Class)中,而其它類別(Class)則透過繼承(Inheritance)的方式來擁有它,如下範例:
這時候就可以使用物件導向的繼承(Inheritance)設計,將共同的屬性(Attribute)或方法(Method)定義在一個類別(Class)中,而其它類別(Class)則透過繼承(Inheritance)的方式來擁有它,如下範例:
# 交通工具(基底類別)
class Transportation:
# 建構式
def __init__(self):
self.color = "white" #顏色屬性
# 駕駛方法
def drive(self):
print("drive method is called.")
# 汽車子類別
class Car(Transportation):
# 加速方法
def accelerate(self):
print("accelerate is method called.")
# 飛機子類別
class Airplane(Transportation):
# 飛行方法
def fly(self):
print("fly method is called.")
我們將Car及Airplane類別(Class)的共同方法drive()定義在一個新的Transportation類別(Class)中,並且新增一個屬性(Attribute)為color。
Transportation類別(Class)就叫父類別或基底類別(Base Class),而Car及Airplane類別(Class)就稱為子類別(Sub Class),在類別名稱的地方透過括號的方式來繼承(Inheritance),藉此擁有父類別公開的屬性(Attribute)及方法(Method),如下範例:
mazda = Car()
mazda.drive()
print(mazda.color)
執行結果
可以看到Car(子類別)的物件mazda擁有Transportation(父類別)的color屬性(Attribute)及drive()方法(Method)。
在淺談Python類別(Class)中有提到Python提供了isinstance()方法來判斷類別(Class)與物件(Object)之間的關係,而這邊Python也提供了issubclass()方法來判斷類別(Class)之間的關係,如下範例:
# Airplane是否為Transportation的子類別
print(issubclass(Airplane, Transportation)) # True
# Airplane是否為object的子類別
print(issubclass(Airplane, object)) # True
# Airplane是否為Car的子類別
print(issubclass(Airplane, Car)) # Fasle
為什麼我們會說Python的所有類別(Class)皆為物件(Object)?也就是因為Python的所有類別(Class)直接或間接的繼承(Inheritance)了物件類別(object),所以我們可以看到第二個print()的結果為True。二、方法覆寫(Method Overriding)
當子類別中定義了和父類別同名的方法(Method),這時候子類別的物件(Object)呼叫這個同名方法時,其中的實作內容將會覆蓋掉父類別的同名方法,這就叫做方法覆寫(Method Overriding),如下範例:
# 交通工具(基底類別)
class Transportation:
# 駕駛方法
def drive(self):
print("Base class drive method is called.")
# 汽車子類別
class Car(Transportation):
# 駕駛方法
def drive(self):
print("Sub class drive method is called.")
mazda = Car()
mazda.drive()
執行結果
# 交通工具(基底類別)
class Transportation:
# 駕駛方法
def drive(self):
print("Base class drive method is called.")
# 汽車子類別
class Car(Transportation):
# 駕駛方法
def drive(self):
super().drive()
print("Sub class drive method is called.")
mazda = Car()
mazda.drive()
執行結果三、多層繼承(Multi-Level Inheritance)
就是繼承(Inheritance)的層級超過一層以上,如下範例:
# 動物類別
class Animal:
pass
# 鳥類類別
class Bird(Animal):
# 飛行方法
def fly(self):
print("fly")
# 鴨子類別
class Duck(Bird):
pass
duck = Duck()
duck.fly()
範例中的Bird類別(Class)繼承(Inheritance)了Animal類別(Class),而Duck類別(Class)又再繼承(Inheritance)了Bird類別,形成了多層繼承(Multi-Level Inheritance)的關係。各位有沒有發現問題?接著我們就可以建立鴨子物件(Object),並且呼叫父類別的fly()方法(Method),但是就邏輯上來說,鴨子不會飛阿~
從這邊就可以知道,雖然繼承(Inheritance)在程式碼的重用(Reusable)上非常的好,但是如果沒有適當的使用就會像此範例一樣產生邏輯上的錯誤。另外,在多層繼承(Multi-Level Inheritance)時,建議別超過兩層,否則反而會增加程式碼的複雜度及難以維護。
四、多重繼承(Multiple Inheritance)
就是子類別繼承(Inheritance)一個以上的父類別,如果沒有適當的使用同樣會產生問題,如下範例:
# 動物類別
class Animal:
def eat(self):
print("Animal eat method is called.")
# 鳥類類別
class Bird:
def eat(self):
print("Bird fly method is called.")
# 鴨子類別
class Duck(Animal, Bird):
pass
duck = Duck()
duck.eat()
執行結果因為Python編譯器在執行多重繼承(Multiple Inheritance)時,會先檢查Duck類別(Class)是否有eat()方法(Method),以這個範例來說沒有,接著Python編譯器會尋找多重繼承(Multiple Inheritance)的第一個類別Animal是否擁有,有的話即執行,並且停止搜尋第二個類別。
如果未來有新的開發人員加入,把Duck類別(Class)的多重繼承類別(Multiple Inheritance)順序對掉,執行結果則變成如下:
會發生這樣的問題就是因為多重繼承(Multiple Inheritance)的各類別(Class)有相同的方法(Method)。要避免此問題,就是各類別應各司其職,避免有相同的方法,如下範例,否則就會產生以上範例的問題。
# 動物類別
class Animal:
def eat(self):
print("Animal eat method is called.")
# 鳥類類別
class Bird:
def walk(self):
print("Bird walk method is called.")
# 鴨子類別
class Duck(Animal, Bird):
pass
duck = Duck()
duck.eat()
從範例中可以看到,Animal和Bird類別(Class)中沒有共同的方法(Method)且有各自的行為,這時候Duck類別(Class)的多重繼承(Multiple Inheritance)就不會產生問題。五、小結
以上就是Python物件導向的繼承(Inheritance)重要觀念教學,適當的使用會讓程式碼的重用性(Reusable)及維護性非常的好,希望看完這篇教學後,對Python繼承(Inheritance)的設計有進一步的認識。如果您喜歡我的文章,請幫我按五下Like(使用Google或Facebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。
有想要看的教學內容嗎?歡迎利用以下的Google表單讓我知道,將有機會成為教學文章,分享給大家😊
請檢查一下
回覆刪除四、多重繼承(Multiple Inheritance)底下的
Animal方法
def eat(sef): 修正self 錯字~~
已修正,感謝您的提醒 :)
刪除簡單明瞭,這種簡潔的範例讓人一目了然,謝謝您。
回覆刪除期待您多分享。
不好意思~
回覆刪除請問 四、多重繼承(Multiple Inheritance) 的範例code在:
# 鳥類類別
class Bird:
def eat(self):
print("Bird fly method is called.")
print的內容應該是"Bird eat method is called."嗎?
謝謝~
我也覺這部份寫錯了
刪除