多型(Polymorphism)是物件導向程式設計(OOP)的核心特性之一,讓不同類別的物件能透過統一介面執行相同方法,但展現各自特定行為,提升程式碼的彈性與可擴展性。它源自希臘文「多形」,如同同一指令在不同物件產生不同結果,讓父類別參考能處理多種子類別實例,無需修改呼叫端程式碼。
多型的基本概念與類型
多型分為兩大類型:
-
編譯時多型(Compile-time/Ad-hoc 多型):透過運算子過載或函式重載實現,編譯器根據參數決定呼叫哪個版本,如 C++ 的
+可加整數或字串。 -
執行時多型(Runtime 多型):透過繼承與介面實現,運行時根據物件實際類型決定行為,最常見於虛擬方法。
核心是「一個介面,多個實作」,讓程式碼依物件類型動態切換邏輯。
方法覆寫與虛擬方法實現
多型依賴繼承與方法覆寫(Override)。父類定義通用方法,子類提供專屬實作:
Python 範例:
class Animal:
def speak(self): # 抽象方法(可視為虛擬)
raise NotImplementedError("子類須實作")
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
animals = [Dog(), Cat()]
for animal in animals: # 父類參考指向子類實例
print(animal.speak()) # 動態執行:汪汪! 喵喵!
父類 Animal 變數 animal 可指向任何子類,speak() 自動呼叫正確版本。
介面與抽象類別的角色
-
抽象類別:定義虛擬方法,子類強制實作,如 Java
abstract void draw();。 -
介面(Interface):純合約,無實作,支援多重實現,如 Java
implements Drawable。
範例(Java):
interface Shape {
void draw(); // 抽象方法
}
class Circle implements Shape {
public void draw() { System.out.println("畫圓形"); }
}
多個不相關類別(如 Circle、Rectangle)實作同一介面,形成多型集合。
多型在不同語言的實現
| 語言 | 機制 | 語法特色 |
|---|---|---|
| Java | 虛擬方法、介面 | @Override 註解 |
| C++ | 虛函數(virtual) | 運行時綁定(Dynamic Binding) |
| Python | Duck Typing | 無顯式虛擬,依方法存在判斷 |
| C# | 虛擬方法、抽象類別 | virtual / override |
| JS | 原型鏈、class extends | 動態語言天生支援 |
Python 的「鴨子類型」(若走路像鴨子叫聲像鴨子,即視為鴨子)最簡潔,無需繼承也能多型。
多型的優點與實際應用
優點包括:
-
擴展性:新增子類無需改呼叫端,符合開閉原則。
-
可替換性:依 Liskov 原則,子類可無縫替換父類。
-
簡化設計:統一介面處理多樣物件。
應用範例:
-
GUI 框架:
Button、TextBox皆繼承Control,container.add(control)統一處理。 -
插件系統:載入不同模組,統一呼叫
plugin.execute()。 -
排序演算法:
List.sort(key=obj.method),物件自訂比較邏輯。
常見問題與最佳實務
問題:錯誤覆寫導致運行時錯誤。解決:使用 @Override 註解、IDE 檢查。
實務:
-
設計穩定介面,避免頻繁變更。
-
偏好介面多於抽象類別,支援多重實現。
-
結合依賴注入(DI),運行時注入多型實例。
-
避免過深繼承,改用組合或策略模式。
多型讓程式如樂高積木,介面固定、內部多變。掌握它能建構彈性架構,從框架到微服務皆適用,是 OOP 轉向專業設計的關鍵一步。