在昨天,我們已經學會了物件導向的基本概念:類別、物件、屬性、方法,並理解了 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 | 寫入驗證 |