當程式越寫越大,我們會發現僅靠函數與變數已經難以有效管理。這時候,一種更有組織性的方式就顯得特別重要 —— 物件導向編程(Object-Oriented Programming, OOP)。
物件導向編程的基礎
物件導向編程的核心是類別(Classes)和物件(Objects)。
類別是一個藍圖,定義了一個物件的屬性和行為。物件是類別的實例,包含實際的數據。
我們已經在先前的文章中開始使用這些概念。
class Dog:
sound = "Woof"
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print(Dog.sound)
在這個例子中,我們創建了一個Dog類別,它有屬性(name和age)和方法(bark)。這個類別可以用來創建多個狗的實例,每個實例都有自己的名字和年齡。
物件導向編程的四大支柱
繼承 (Inheritance)
允許類別從其他類別獲取屬性和方法
多型 (Polymorphism)
允許對不同類型的物件執行相同的操作
抽象 (Abstraction)
隱藏複雜性,只展示必要的部分
封裝 (Encapsulation)
將數據和方法打包成一個單元,限制外部訪問
這四個支柱是物件導向編程的基礎。掌握這些概念將使您能夠創建更強大、更可維護的程式。
繼承 (Inheritance)
繼承允許我們創建一個新的類別,該類別獲取現有類別的所有屬性和方法。這就像在現實生活中,孩子從父母那裡繼承特徵一樣。
在物件導向編程中,我們可以創建一個父類別(Parent Class)和一個子類別(Child Class):
class Animal: # 父類別
def eat(self):
print("Nom Nom Nom...eating food!")
class Dog(Animal): # 子類別
def bark(self):
print('Woof!')
class Cat(Animal): # 子類別
def meow(self):
print('Meow!')
在這個例子中,Dog和Cat類別都繼承自Animal類別,因此它們都可以使用eat()方法。

繼承的優勢
代碼重用
繼承允許我們在多個類別之間共享代碼,減少重複。在我們的例子中,eat()方法只需定義一次,就可以被所有動物類別使用。
層次結構
繼承建立了類別之間的層次關係,反映了實體之間的自然關係。例如,所有的狗和貓都是動物,因此它們的類別可以繼承自動物類別。
專一性
子類別可以添加特定於自己的方法和屬性,同時保留父類別的共同特徵。例如,狗可以吠叫,貓可以喵喵叫,但兩者都可以吃東西。
讓我們看一下繼承的實際應用:
fluffy = Dog()
zoomie = Cat()
fluffy.eat() # 輸出: Nom Nom Nom...eating food!
zoomie.eat() # 輸出: Nom Nom Nom...eating food!
方法覆寫 (Method Overriding)
有時,子類別可能需要改變從父類別繼承的方法的行為。這稱為方法覆寫。
class Animal:
def __init__(self, name):
self.name = name
def make_noise(self):
print("{} says, Grrrr".format(self.name))
class Cat(Animal):
def make_noise(self):
print("{} says, Meow!".format(self.name))
在這個例子中,Cat類別覆寫了make_noise()方法,使其發出”喵喵”聲而不是一般的動物聲音。
當我們創建一個Cat實例並調用make_noise()方法時,它會使用Cat類別中定義的版本,而不是Animal類別中的版本。
使用super()函數
當覆寫方法時,我們有時候仍然想要使用父類別方法的行為。Python提供了super()函數來實現這一點。
class Animal:
def __init__(self, name, sound="Grrrr"):
self.name = name
self.sound = sound
def make_noise(self):
print("{} says, {}".format(self.name, self.sound))
class Cat(Animal):
def __init__(self, name):
super().__init__(name, "Meow!")
pet_cat = Cat("Rachel")
pet_cat.make_noise() # 輸出: Rachel says, Meow!
在這個例子中,Cat類別的__init__方法使用super().__init__()調用父類別的初始化方法,同時提供了一個特定的聲音”Meow!”。這樣,我們可以保留父類別的行為,同時添加或修改子類別特定的行為。
多重繼承 (Multiple Inheritance)
Python允許一個類別從多個父類別繼承,這稱為多重繼承。
多重繼承有兩種主要形式:
- 多層繼承:類別從其父類別和祖父類別繼承。例如,AngryDog繼承自Dog,而Dog繼承自Animal。
- 直接多重繼承:類別直接從兩個或多個類別繼承。例如,Hybrid繼承自Dog和Wolf。
多重繼承可以非常強大,但也需要小心使用,因為它可能導致命名衝突和複雜的行為。在使用super()時,Python會按照類別定義中列出父類別的順序來解析方法調用。
多層繼承的例子
Animal類別
基本動物特性,如名字和打招呼的能力
class Animal:
def __init__(self, name):
self.name = name
def say_hi(self):
print("{} says, Hi!".format(self.name))
Cat類別
繼承自Animal,獲得其所有特性
class Cat(Animal):
pass # 不添加新功能
AngryCat類別
繼承自Cat,因此間接繼承自Animal
class Angry_Cat(Cat):
pass # 不添加新功能
使用多層繼承:
my_pet = Angry_Cat("Mr. Cranky")
my_pet.say_hi() # 輸出: Mr. Cranky says, Hi!
直接多重繼承的例子
直接多重繼承允許一個類別從兩個或多個類別直接繼承:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def action(self):
print("{} wags tail. Awwww".format(self.name))
class Wolf(Animal):
def action(self):
print("{} bites. OUCH!".format(self.name))
class Hybrid(Dog, Wolf):
def action(self):
super().action() # 調用第一個父類別的方法
Wolf.action(self) # 明確調用Wolf的方法
my_pet = Hybrid("Fluffy")
my_pet.action()
# 輸出:
# Fluffy wags tail. Awwww
# Fluffy bites. OUCH!
注意:在調用Wolf.action(self)時,我們需要明確傳遞self參數,以確保方法接收到正確的實例。
在多重繼承中,super().action()調用的是Hybrid類別定義中列出的第一個父類別(Dog)的action()方法。如果要調用其他父類別的方法,需要明確指定類別名稱。
結語
繼承 (Inheritance) 是OOP當中最常做使用的。接下來將進一步探討 OOP 的 多型 (Polymorphism)、抽象 (Abstraction) 和封裝 (Encapsulation),幫助你完整掌握 OOP 的四大支柱,進而寫出更具彈性與可維護性的程式。