
在掌握了類別與物件的基礎後,我們要進一步探討 OOP 的三大支柱:封裝 (Encapsulation)、繼承 (Inheritance) 與 多型 (Polymorphism)。本章將聚焦於繼承與多型,這是建構大型、可擴充系統的基石。
1. 繼承 (Inheritance):站在巨人的肩膀上
繼承允許我們定義一個「子類別」(Child Class),它會自動擁有「父類別」(Parent Class) 的所有屬性與方法。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
# Dog 繼承自 Animal
class Dog(Animal):
def speak(self):
return "Woof!"
# Cat 繼承自 Animal
class Cat(Animal):
def speak(self):
return "Meow!"
d = Dog("Buddy")
print(f"{d.name} says {d.speak()}") # Buddy says Woof!
在這個例子中,Dog 和 Cat 不需要重新寫 __init__,因為它們繼承了 Animal 的建構子。
2. super():呼叫父類別
當我們在子類別「透過覆寫 (Override)」修改了父類別的方法,但又想保留父類別原有的邏輯時,就要用 super()。
class Bird(Animal):
def __init__(self, name, can_fly):
# 呼叫父類別的 __init__ 來初始化 name
super().__init__(name)
self.can_fly = can_fly
def speak(self):
# 先執行父類別的 speak (雖然這裡只回傳 "...")
original_sound = super().speak()
return f"{original_sound} Tweet!"
b = Bird("Tweety", True)
print(b.name, b.can_fly)
super() 讓程式碼更具彈性,就算未來父類別改名或邏輯變動,子類別通常不需要修改。
3. 多重繼承與 MRO (Method Resolution Order)
Python 支援 多重繼承,也就是一個類別可以有多個父類別。但如果兩個父類別都有同名的方法,Python 該呼叫哪一個?
這取決於 MRO (方法解析順序)。Python 使用 C3 Linearization 演算法來決定繼承順序。
class A:
def process(self):
print("A process")
class B(A):
def process(self):
print("B process")
class C(A):
def process(self):
print("C process")
# D 同時繼承 B 和 C
class D(B, C):
pass
d = D()
d.process()
# 輸出: B process
# 因為 D 繼承列表是 (B, C),Python 會先找 B
print(D.mro())
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
理解 MRO 對於使用像是 Django Mixin 這類的設計模式至關重要。
4. 多型 (Polymorphism):「鴨子型別」
Python 是動態語言,我們不須像 Java 或 C++ 那樣明確定義介面。Python 奉行 鴨子型別 (Duck Typing):
「如果它走起來像鴨子,叫起來像鴨子,那它就是鴨子。」
def animal_sound(animal):
# 不需要檢查 animal 是不是 Animal 的子類別
# 只要它有 speak() 方法就可以
print(animal.speak())
class Car:
def speak(self):
return "Vroom!"
animal_sound(Dog("Doge")) # Woof!
animal_sound(Car()) # Vroom! (雖然車不是動物,但也能跑!)
這賦予了 Python 極大的靈活性。
5. 抽象基礎類別 (ABC)
雖然鴨子型別很方便,但有時我們希望強制子類別必須實作某些方法。這時可以使用 abc 模組。
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
# 如果不實作 area,實例化時會噴錯
def area(self):
return 3.14 * self.radius ** 2
# s = Shape() # TypeError: Can't instantiate abstract class
c = Circle(5)
print(c.area())
6. 總結
繼承與多型是讓程式碼模組化、可維護的關鍵。
本章重點回顧:
- Inheritance: 子類別繼承父類別的特性。
- Override: 子類別可以覆寫父類別的方法。
- super(): 用於呼叫父類別的方法,特別是在
__init__中。 - MRO: 多重繼承時,Python 尋找方法的順序 (由左至右,由下而上)。
- Duck Typing: Python 的多型不需要繼承特定介面,只要方法存在即可。
下一章,我們將揭開 Python 物件的神秘面紗,探討 魔術方法 (Magic Methods),讓你的自訂物件能像內建型別一樣使用 +, -, len() 等運算子!
延伸閱讀: