繼承(Inheritance)是物件導向程式設計(OOP)的核心特性之一,讓子類別(子類)能自動取得父類別(父類)的屬性與方法,實現程式碼重用、階層擴展與多型基礎。它就像生物遺傳,子類繼承父類特徵,同時可新增或修改自身功能,避免重複撰寫相似邏輯,大幅提升程式模組化與維護性。
繼承的基本概念與語法
繼承建立「is-a」關係,例如「狗 is-a 動物」,子類擴展父類。語法上,子類在宣告時指定父類名稱:
-
Python:
class Dog(Animal): -
Java:
class Dog extends Animal {}
子類自動擁有父類的公開成員(屬性、方法),並可透過 super() 呼叫父類建構子或方法。例如:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "某種聲音"
class Dog(Animal):
def speak(self): # 方法覆寫
return f"{self.name} 汪汪!"
父類別與子類別的關係
父類別提供通用功能,子類專注特定行為。繼承形成樹狀階層:
-
單一繼承:一子一父,最簡單穩定。
-
多層繼承:如
Poodle(Dog),Dog 繼承 Animal,形成祖父-父-子鏈。 -
多重繼承:子類同時繼承多父(如 Python 支援),但易產生「菱形問題」(多條路徑存取同一祖先)。
存取順序遵循 MRO(Method Resolution Order),確保方法解析明確。
方法覆寫與擴展功能
子類可覆寫(Override)父類方法,提供專屬實作,實現多型;或擴展父類:
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 呼叫父類建構子
self.breed = breed # 新增屬性
def speak(self):
return super().speak() + " 但更響亮!" # 擴展父類
覆寫讓同一介面展現不同行為,提升程式彈性。
存取修飾符與繼承範圍
繼承受存取權限限制:
-
公開(Public):全繼承。
-
受保護(Protected):子類可存取,如
_private(Python 慣例)。 -
私有(Private):不繼承,如
__private。
Java 使用 protected 關鍵字,C# 有 internal 等級別。
繼承的優點與實際應用
優點包括:
-
程式碼重用:通用邏輯置父類,避免重複。
-
維護簡化:修改父類自動影響子類。
-
多型基礎:父類參考指向子類實例,運行時決定行為。
應用如 GUI 框架:Button 繼承 Control,新增點擊事件;遊戲中 Enemy 繼承 Character,共享移動邏輯但有獨特攻擊。
語言差異比較
| 語言 | 支援多重繼承 | 語法關鍵字 | 特色 |
|---|---|---|---|
| Python | 是 | () |
MRO 解析、Mixin 模式 |
| Java | 否(僅介面) | extends |
單根繼承樹 |
| C++ | 是 | : |
虛基類解決菱形問題 |
| JS | 原型式 | extends |
ES6 類別語法糖 |
常見問題與最佳實務
問題:過深繼承導致「脆弱基類」(Fragile Base Class)問題,父類變更影響子類。解決:偏好組合(Has-a)而非繼承,遵循「Liskov 替換原則」(子類須可替換父類無異樣)。
實務:
-
抽象類別強制子類實作特定方法。
-
使用介面(Interface)定義合約,避免實作繼承。
-
避免神類(過載父類),保持淺層階層。
繼承是 OOP 強大機制,但需謹慎使用。結合封裝與多型,形成完整設計模式,讓程式如樂高積木般靈活組裝。