Python 繼承(Python Inheritance)
這篇 Python 繼承教學將帶你認識類別之間的「親子關係」:子類別自動擁有父類別的屬性與方法,再加上自己特有的部分。共通邏輯寫一次放父類別,差異部分各自實作——這就是繼承解決的問題。
基本繼承
類別名稱後面加 (父類別) 就是繼承:
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(f"{self.name} 在吃東西")
class Dog(Animal): # Dog 繼承 Animal
def bark(self):
print(f"{self.name}:汪汪!")
dog = Dog("小黑")
dog.eat() # 繼承自 Animal,不用重寫
dog.bark() # Dog 自己的方法
執行輸出:
小黑 在吃東西
小黑:汪汪!
方法覆寫(Override)
子類別定義同名方法,就會「蓋掉」父類別的版本:
class Animal:
def speak(self):
print("動物發出聲音")
class Dog(Animal):
def speak(self): # 覆寫父類別的 speak
print("汪汪!")
class Cat(Animal):
def speak(self):
print("喵~")
Dog().speak()
Cat().speak()
執行輸出:
汪汪!
喵~
super():呼叫父類別的方法
子類別擴充 __init__ 時,先用 super().__init__() 把父類別的初始化做完,再加自己的:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 讓父類別處理 name
self.breed = breed # 自己只處理新增的部分
dog = Dog("小黑", "柴犬")
print(dog.name, dog.breed)
執行輸出:
小黑 柴犬
多型(Polymorphism)
多型=「同一個操作,不同型別各自有不同表現」。好處是呼叫端不用管物件是哪個子類別:
class Dog:
def speak(self):
return "汪汪!"
class Cat:
def speak(self):
return "喵~"
animals = [Dog(), Cat(), Dog()]
for a in animals:
print(a.speak()) # 不用判斷型別,各自表現
執行輸出:
汪汪!
喵~
汪汪!
注意 Python 的多型不要求共同父類別——只要有同名方法就能這樣呼叫(俗稱鴨子型別:走起來像鴨子、叫起來像鴨子,那就是鴨子)。
isinstance():檢查型別
需要判斷物件型別時用 isinstance(),繼承關係也算:
class Animal: pass
class Dog(Animal): pass
dog = Dog()
print(isinstance(dog, Dog))
print(isinstance(dog, Animal)) # Dog 是 Animal 的子類別,也算
print(isinstance(dog, str))
執行輸出:
True
True
False
常見錯誤
1. 子類別 __init__ 忘了呼叫 super().__init__()
子類別定義了自己的 __init__ 就會完全取代父類別的,父類別設定的屬性全部消失,之後存取就報 AttributeError。記住:覆寫 __init__ 時第一件事就是 super().__init__(...)。
2. 繼承層級太深
A 繼承 B 繼承 C 繼承 D⋯⋯追一個方法要翻好幾層。實務原則:繼承兩層內解決,更複雜的關係改用「組合」(物件裡放物件)。
3. 用 type() 判斷型別而非 isinstance()
type(dog) == Animal 對子類別會是 False,破壞多型的彈性。判斷型別一律用 isinstance()。
總結
class Dog(Animal) 繼承、同名方法覆寫、super() 呼叫父類別版本(覆寫 __init__ 必加);多型讓呼叫端不用管實際型別;型別判斷用 isinstance()。下一篇認識讓自訂類別融入 Python 語法的特殊方法(Magic Methods)。