在昨天,我們已經學會了物件導向的基本概念:類別、物件、屬性、方法,並理解了 self
與 __init__
的作用。這些基礎讓我們能夠建立「藍圖」並產生對應的物件。
然而,真實的專案通常更複雜:
super()
)。@property
。用生活來比喻:
super()
:像是小孩遇到不會的事,先請父母處理,再加上自己的做法。今天重點在於讓程式設計更有彈性、更安全,也能用更貼近現實的方式來建模。學會這些後,你會發現物件導向不只是「整理程式碼」,而是真正能讓程式具有擴充性與可維護性的核心。
繼承:子類別會繼承父類別屬性與方法。
多型:不同子類別各自覆寫同一個方法,表現出不同行為。
class Father:
def __init__(self, name):
self.name = name
def skill(self):
return "會開車"
# [子類別] 小孩繼承爸爸
class Son(Father):
def skill(self):
return "打電動"
class Daughter(Father):
def skill(self):
return "彈鋼琴"
family = [Father("爸爸"), Son("小明"), Daughter("小美")]
for member in family:
print(f"{member.name}:{member.skill()}")
super()
的用途子類別要沿用父類別的初始化邏輯時,用 super()
呼叫父類別版本:
class Father:
def __init__(self, name):
self.name = name
def skill(self):
return "會開車"
class Son(Father):
def __init__(self, name, hobby):
super().__init__(name) # 呼叫父類別 __init__
self.hobby = hobby
def skill(self):
return super().skill() + ",也會打電動"
class Daughter(Father):
def __init__(self, name, hobby):
super().__init__(name)
self.hobby = hobby
def skill(self):
return super().skill() + ",也會彈鋼琴"
# 建立物件
dad = Father("爸爸")
son = Son("小明", "打電動")
daughter = Daughter("小美", "彈鋼琴")
print(f"{dad.name}:{dad.skill()}")
print(f"{son.name}:{son.skill()}")
print(f"{daughter.name}:{daughter.skill()}")
@property
讓屬性在存取時多一層驗證或計算,外部使用方式仍像操作屬性。
class Student:
def __init__(self, name, grade):
self.name = name
self._grade = None
self.grade = grade # setter 驗證
@property
def grade(self):
return self._grade
@grade.setter
def grade(self, value):
if not (0 <= value <= 100):
raise ValueError("成績必須在 0~100")
self._grade = value
# 建立學生物件
s1 = Student("小明", 90)
# 讀取成績(實際上呼叫的是 @property 的 getter)
print(s1.grade) # 輸出:90
# 修改成績(實際上呼叫的是 setter)
s1.grade = 75
print(s1.grade) # 輸出:75
# 嘗試給不合法的數值
try:
s1.grade = 150 # 超過 100,不合法
except ValueError as e:
print("錯誤:", e)
# 讀取名字(普通屬性,不受影響)
print(s1.name) # 輸出:小明
類型 | 宣告方式 | 常見用途 |
---|---|---|
實例方法 | def m(self, ...) |
操作物件資料 |
類別方法 | @classmethod def m(cls) |
類別邏輯、替代建構子 |
靜態方法 | @staticmethod def m() |
工具性函數 |
封裝 getter | @property |
攔截屬性讀取 |
封裝 setter | @x.setter |
寫入驗證 |