在程式設計中,如果很多類別有共通的屬性與方法,我們不需要重複寫,而是可以定義一個「父類別」,其他「子類別」去繼承它。
好處:
class 父類別:
# 定義共通的屬性與方法
class 子類別(父類別):
# 自動繼承父類別的屬性與方法
在繼承的情況下,子類別會自動擁有父類別的屬性與方法。
但如果子類別需要「修改」或「重新定義」父類別的方法,就可以使用 方法覆寫(Override)。
# 父類別
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 發出聲音")
# 子類別
class Dog(Animal):
def speak(self): # 覆寫父類別的方法
print(f"{self.name} says: Woof!")
class Cat(Animal):
def speak(self):
print(f"{self.name} says: Meow!")
dog = Dog("MiMi")
cat = Cat("Gogo")
dog.speak()
cat.speak()
輸出:
MiMi says: Woof!
Gogo says: Meow!
父類別
子類別
Dog 和 Cat 都繼承了 Animal。
但它們重新定義了 同名方法 speak(),這就覆蓋了父類別的版本。
也就是說:
如果你建立 Dog("MiMi") 然後呼叫 speak(),程式會跑 Dog 類別裡的 speak(),而不是 Animal 的。
同理,Cat("Gogo") 會執行 Cat 的 speak()。
Dog 與 Cat 沒有重新寫建構子(init),所以會沿用父類別的。
如果需要擴充,可以使用 super() 來呼叫父類別的初始化方法。
有時候子類別需要「先做父類別的事,再做自己的事」。
這時候可以用 super() 呼叫父類別的方法:
class Bird(Animal):
def __init__(self, name, can_fly=True):
super().__init__(name) # 呼叫父類別建構子
self.can_fly = can_fly
def speak(self):
print(f"{self.name} chirps!")
def fly(self):
if self.can_fly:
print(f"{self.name} is flying!")
else:
print(f"{self.name} can't fly...")
parrot = Bird("Polly")
parrot.speak()
parrot.fly()
多型的意思是「相同的方法名稱,可以有不同的實作」。
在 Python 中,因為是動態語言,只要物件有該方法,就能呼叫,不必在意類別。
animals = [Dog("Mimi"), Cat("Gogo"), Bird("Polly")]
for animal in animals:
animal.speak() # 自動依照物件型別呼叫對應方法
輸出:
Mimi says: Woof!
Gogo says: Meow!
Polly chirps!
這就是多型:同樣是 speak(),但每個物件的行為不同。
今天學到繼承與多型,想要補充Java的處理介面、抽象類別、存取修飾詞(public/private/protected)
類別 / 方法 | 特點 |
---|---|
抽象類別 (Abstract Class) | 可以包含 抽象方法 和 具體方法(已經實作好的方法) 提供子類別繼承的「模板」與共用功能 |
抽象方法 (Abstract Method) | 只有方法簽名(名稱與參數),沒有具體實作 子類別必須覆寫(override)這些方法,否則子類別本身也會是抽象類別 |
抽象方法使用 abstract聲明,且不能包含方法體(無括號)
明天要進行一個綜合練習,結合模組、OOP、以及前面學過的基礎功能,嘗試做一個小系統。這會是一個把所有東西串起來的挑戰!