6.1 繼承 — 很簡單啦
繼承是物件導向程式設計(OOP)的一個基本概念,它允許一個類別(稱為子類別)繼承另一個類別的屬性和方法(稱為父類別或超類別)。
這種方法可以創建比較通用的類別,重複使用代碼,提升代碼的組織性和可維護性。
為啥要用繼承呢?
假設你需要寫點代碼,並決定以類別的形式來做。然後你發現項目中已經有個類別,幾乎做了你需要的一切。你可以直接複製這個類別的代碼,然後用得開心。
或者你可以「像是複製」的樣子。你可以定義那個類別為你類別的父類,然後 Python 會給你的類別添加父類的行為。
想像一下你是大自然,想創造一隻狗。是從細菌開始花十億年創造一隻狗更快,還是馴化狼需要大約二十萬年更快?
基本繼承範例
假設你有一個父類別 Animal
,帶有屬性 name:
class Animal:
def __init__(self, name):
self.name = name
我們想為它創建兩個子類別 — Dog
和 Cat
,還要給它們都加上方法 speak
:
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
在上面的例子中,子類別 Dog
和 Cat
繼承自 Animal
並添加了 speak
方法。
類別 Dog
:
- 繼承了
Animal
的屬性name
。 - 添加了
speak
方法,返回特定於狗的字符串。
類別 Cat
:
- 繼承了
Animal
的屬性name
。 - 添加了
speak
方法,返回特定於貓的字符串。
最終代碼如下所示:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # 會輸出:Buddy says Woof!
print(cat.speak()) # 會輸出:Whiskers says Meow!
在這個例子中,Animal
是父類別,Dog
和 Cat
是子類別。子類別繼承自父類別 Animal
的屬性 name
和方法 __init__
,並添加了 speak
方法。
6.2 繼承的幕後運作
如果你給你的類別添加了父類,這就像是你把父類的代碼複製到你的類別裡一樣。
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name):
super().__init__(name) # 呼叫父類別的構造函數
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def __init__(self, name):
super().__init__(name) # 呼叫父類別的構造函數
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # 會輸出:Buddy says Woof!
print(cat.speak()) # 會輸出:Whiskers says Meow!
這個描述並不完全準確,但如果你從來沒有接觸過繼承的概念,可以暫時這樣思考。我們之後會加上更多細節。
6.3 繼承的層次結構
在設計大規模類別群組的複雜模型時,你可能會遇到整個繼承的層次結構。
例如,你有一個類別 Animal
— 這是所有動物的基類:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement abstract method")
我們甚至還給它添加了 speak
方法,但是因為抽象的動物不會說話,這個方法只會拋出 NotImplementedError
— 這是標準做法。
然後我們添加了中間類別,這些類別對應於動物的分類:Mammal
是哺乳動物,Bird
是鳥類。
class Mammal(Animal):
def __init__(self, name, fur_color):
super().__init__(name) # 呼叫父類別的構造函數
self.fur_color = fur_color
class Bird(Animal):
def __init__(self, name, wing_span):
super().__init__(name) # 呼叫父類別的構造函數
self.wing_span = wing_span
def fly(self):
return f"{self.name} is flying with a wingspan of {self.wing_span} meters."
最後一步是創建具體的動物類別:
class Dog(Mammal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Mammal):
def speak(self):
return f"{self.name} says Meow!"
class Parrot(Bird):
def speak(self):
return f"{self.name} says Squawk!"
通常最終的代碼會和這些類別一起工作:
animals = [Dog("Buddy", "brown"), Cat("Whiskers", "white"), Parrot("Polly", 0.5)]
for animal in animals:
print(animal.speak())
print(f"{dog.name} has {dog.fur_color} fur.") # 會輸出:Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.") # 會輸出:Whiskers has white fur.
print(parrot.fly()) # 會輸出:Polly is flying with a wingspan of 0.5 meters.
雖然從技術上講,創建數十個祖先的繼承層次結構沒有禁止,但是要記住在沒有必要的情況下最好保持簡單。簡單才是真正的力量。
GO TO FULL VERSION