在前一篇文章中,我們已經認識了物件導向編程(OOP)的基礎,並深入學習了 繼承 (Inheritance)。
繼承幫助我們重用程式碼並建立層次結構,除了繼承之外,OOP 還有三個同樣重要的特性:
- 多型 (Polymorphism):相同的操作,能夠根據不同物件而展現不同的行為。
- 抽象 (Abstraction):隱藏細節,強調必要的行為,幫助我們建立清晰的設計契約。
- 封裝 (Encapsulation):將資料與方法打包,保護內部細節,僅提供必要的接口給外部使用。
這三個特性讓程式碼更靈活、更安全、更容易維護。
多型 (Polymorphism)
多型是物件導向編程的另一個重要支柱,它允許我們對不同類型的物件執行相同的操作。
在Python中,多型可以通過多種方式實現:
- 方法覆寫:不同類別可以有同名但行為不同的方法
- 運算符重載:同一個運算符可以對不同類型的物件執行不同的操作
多型的一個主要優點是它允許我們編寫更通用、更靈活的代碼,不必關心物件的具體類型。

多型的例子
不同類別的相同方法名
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))
class Robot:
def make_noise(self):
print("beep.boop...BEEEEP!!!")
使用多型
an_animal = Animal("Bear")
my_pet = Cat("Maisy")
my_vacuum = Robot()
objects = [an_animal, my_pet, my_vacuum]
for o in objects:
o.make_noise()
# 輸出:
# "Bear says, Grrrr"
# "Maisy says, Meow!"
# "beep.boop...BEEEEP!!!"
在這個例子中,我們可以調用不同物件的make_noise()方法,而不需要知道它們的具體類型。這就是多型的力量!
Dunder方法和運算符重載
Dunder方法(雙下劃線方法)是Python中的特殊方法,允許我們自定義類別的行為。例如:
- __init__(): 構造函數
- __repr__(): 字符串表示
- __add__(): 加法運算符
- __len__(): 長度函數
通過定義這些方法,我們可以實現運算符重載,使運算符對不同類型的物件有不同的行為。
class Animal:
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
def __add__(self, another_animal):
return Animal(self.name + another_animal.name)
a1 = Animal("Horse")
a2 = Animal("Penguin")
a3 = a1 + a2
print(a1) # 輸出: Horse
print(a2) # 輸出: Penguin
print(a3) # 輸出: HorsePenguin
在這個例子中,我們定義了__add__()方法,使得可以使用+運算符將兩個Animal物件”加”在一起,創建一個新的Animal物件,其名字是兩個原始物件名字的組合。
抽象 (Abstraction)
抽象是物件導向編程的第三個支柱,它幫助我們隱藏複雜性,只展示必要的部分。
在Python中,我們可以使用抽象基類(Abstract Base Classes,ABC)來實現抽象。抽象類不能被實例化,它們只是作為其他類別的模板。
from abc import ABC, abstractmethod
class Animal(ABC):
def __init__(self, name):
self.name = name
@abstractmethod
def make_noise(self):
pass
class Cat(Animal):
def make_noise(self):
print("{} says, Meow!".format(self.name))
在這個例子中,Animal是一個抽象類,它定義了所有動物應該有的基本行為(make_noise),但沒有實現它。子類別(如Cat)必須實現這個方法,否則會出錯。

抽象的優勢
強制一致性
抽象類可以確保所有子類別實現特定的方法,保持API的一致性。在我們的例子中,所有Animal的子類別都必須實現make_noise()方法。
定義契約
抽象類定義了一個”契約”,規定了子類別必須遵循的行為。這有助於確保代碼的正確性和可靠性。
提高設計質量
抽象鼓勵我們思考類別的核心行為和責任,而不是具體的實現細節。這有助於創建更好的類別層次結構。
抽象是一個強大的工具,可以幫助我們設計更加模組化、可維護的程式。通過定義抽象類別,我們可以確保類別層次結構的一致性和正確性。
封裝 (Encapsulation)
封裝是物件導向編程的第四個支柱,它涉及將數據和方法打包成一個單元,並限制對內部細節的訪問。
在許多語言中,有三種訪問修飾符:
- 公共(Public):可以從任何地方訪問
- 受保護(Protected):只能從同一模塊訪問
- 私有(Private):只能從定義它們的類別內部訪問
Python沒有嚴格的訪問控制,但有一些約定:
- 單下劃線(_x):表示受保護的成員
- 雙下劃線(__x):表示私有成員(名稱會被修改)
封裝幫助我們隱藏實現細節,只暴露必要的接口。這樣,我們可以在不影響用戶代碼的情況下更改內部實現。

Getter、Setter和Deleter
Getter、Setter和Deleter是實現封裝的一種方式,它們允許我們控制對類別屬性的訪問和修改。
class Animal:
def __init__(self, name):
self._name = name
self._age = None
def get_age(self):
return self._age
def set_age(self, new_age):
if isinstance(new_age, int):
self._age = new_age
else:
raise TypeError
def delete_age(self):
print("_age Deleted")
del self._age
在這個例子中,我們使用getter(get_age)、setter(set_age)和deleter(delete_age)來控制對_age屬性的訪問、修改和刪除。setter還包含驗證邏輯,確保年齡只能是整數。
結語
至此,我們已經完整認識了 OOP 的四大支柱:繼承、多型、抽象、封裝。
掌握這些概念後,你不僅能寫出可以運行的程式,更能設計出 模組化、可維護、可擴展 的架構。