iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0

前言

昨天我們學了「繼承」,知道子類別可以直接使用父類別的方法和屬性,
這樣程式就不需要「重複」寫相同的功能,可以省時、也可以省空間!

今天,我們要進階學三個概念:

  1. 多層繼承(Multilevel Inheritance):就像家族傳承,祖父的功能可以傳給父親,再傳給子女。
  2. 多重繼承(Multiple Inheritance):一個子類別可以同時繼承多個父類別的功能,像同時擁有多種技能。
  3. 私有方法(Private Methods):有些功能或資料不希望外部隨意修改或使用,必須保護起來。

學會這三個概念後,你就能設計更靈活、可重複使用、也更安全的程式。

一、多層繼承(Multilevel Inheritance)

所謂「多層繼承」,其實就是「祖孫三代」的概念。
A 類生了 B 類,B 類又生了 C 類,最後 C 類就能用到 A 和 B 的功能。

範例:家族血統

class Grandparent:
    def family_name(self):
        print("Family name: Lin")

class Parent(Grandparent):
    def hobby(self):
        print("Parent loves cooking.")

class Child(Parent):
    def school(self):
        print("Child goes to elementary school.")

c = Child()
c.family_name()
c.hobby()
c.school()

輸出:

https://ithelp.ithome.com.tw/upload/images/20251007/20164721SDlhqwbbFW.png

說明:

  • Child 不只繼承 Parent 的東西,也間接繼承 Grandparent
  • Python 在找方法時會「一層層往上找」。
  • 這就是多層繼承最直覺的力量——功能可以世代傳承!

💡 重點提示:

Python 會按照繼承鏈(Method Resolution Order, MRO)一路往上找,直到找到方法或到最上層的 object 類別為止。

二、多重繼承(Multiple Inheritance)

所謂「多重繼承」,意思是 一個子類別可以同時繼承多個父類別
就像一個人可能同時是「老師」也是「Youtuber」,可以繼承兩種技能。

範例:多重職業角色

class Teacher:
    def teach(self):
        print("Teaching students about Python.")

class Youtuber:
    def record(self):
        print("Recording a new coding tutorial video.")

class TeacherYoutuber(Teacher, Youtuber):
    def rest(self):
        print("Finally resting after a long day.")

ty = TeacherYoutuber()
ty.teach()
ty.record()
ty.rest()

說明:

  • TeacherYoutuber 同時繼承了兩個父類別。
  • 所以他既能「教課」,又能「錄影片」。
  • 這樣的設計能把不同功能拆分在不同類別,再靈活組合!是不是蠻有趣的!也很省力~

輸出:

https://ithelp.ithome.com.tw/upload/images/20251007/20164721KkyAUCDKRp.png

⚠️ 注意:小心!名字衝突會打架

如果兩個父類別都有同名方法呢?

class A:
    def greet(self):
        print("Hello from A")

class B:
    def greet(self):
        print("Hello from B")

class C(A, B):
    pass

c = C()
c.greet()
print(C.mro())

輸出:
https://ithelp.ithome.com.tw/upload/images/20251007/20164721Bm5z4LWEq4.png

說明:

  • Python 按照「左到右」順序找方法。
  • 先找到 Agreet(),就不會再去找 B
  • 這個順序就是 MRO (Method Resolution Order)
    如果想看順序,用 ClassName.mro() 就能查!

三、私有方法與屬性(Private Methods / Attributes)

有時候,我們不想讓外部隨意修改或呼叫某些資料。
例如銀行帳戶密碼、公司內部的秘密函式、或某段不該被外部程式動到的邏輯。
這時候可以用「雙底線」開頭的變數或方法,讓它變成「私有」的。

範例1:銀行帳戶

class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.__balance = balance  # 私有屬性

    def deposit(self, amount):
        self.__balance += amount
        print(f"Deposited {amount}. Current balance: {self.__balance}")

    def __secret_report(self):
        print("This is a secret internal report.")

account = BankAccount("Alice", 1000)
account.deposit(500)

print(account.owner)
print(account.__balance)  # 錯誤:AttributeError

輸出:
https://ithelp.ithome.com.tw/upload/images/20251007/2016472128UltkvodD.png

說明:

  • __balance 是私有屬性,外部無法直接存取。
  • 只能透過公開的方法(像 deposit())來操作。
  • 這樣做可以「保護資料安全」,防止外部亂改。

範例2:

class Member:
    def __init__(self, username, password):
        self.username = username
        self.__password = password  # 私有屬性

    def login(self):
        pw = input("請輸入密碼:")
        if pw == self.__password:
            print(f"✅ 歡迎回來,{self.username}!")
        else:
            print("❌ 密碼錯誤,登入失敗。")

user = Member("Sharon", "12345")
user.login()

這就是私有變數的實際應用!

輸出:
https://ithelp.ithome.com.tw/upload/images/20251007/201647211MzdFcVQ5e.png

範例3:

class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.__balance = balance  # 私有屬性

    def deposit(self, amount):
        self.__balance += amount
        print(f"💰 存入 {amount} 元,目前餘額:{self.__balance}")

    def withdraw(self, amount):
        if amount > self.__balance:
            print("⚠️ 餘額不足!")
        else:
            self.__balance -= amount
            print(f"💸 提領 {amount} 元,剩餘餘額:{self.__balance}")

    def get_balance(self):
        return self.__balance

account = BankAccount("Alice", 1000)
account.deposit(500)
account.withdraw(300)
print("總餘額:",account.get_balance(),"元")

print(account.__balance)  # ❌ 錯誤!

輸出:

https://ithelp.ithome.com.tw/upload/images/20251007/20164721AtRPHI1SrV.png

說明:

  • __balance 是私有的,外部不能直接改。
  • 透過 get_balance() 才能安全地取值。

四、實戰演練:動物園管理系統

# ===== 多層繼承 =====
class Animal:
    def __init__(self, name, age, species):
        self.name = name
        self.age = age
        self.species = species
        self.__health = 60  # 私有屬性

    def info(self):
        print(f"{self.name} ({self.species}), 年齡: {self.age}, 健康: {self.__health}")

    def feed(self, amount):
        self.__health += amount
        self.__check_health()
        print(f"餵食 {self.name} {amount} 點,健康值變成 {self.__health}")

    def __check_health(self):  # 私有方法
        if self.__health > 100:
            self.__health = 100
        elif self.__health < 0:
            self.__health = 0

class Mammal(Animal):
    def __init__(self, name, age, species, fur_color):
        super().__init__(name, age, species)
        self.fur_color = fur_color

class Lion(Mammal):
    def roar(self):
        print(f"{self.name} 發出咆哮聲!")

# ===== 多重繼承 =====
class Bird(Animal):
    def __init__(self, name, age, species, wing_span):
        super().__init__(name, age, species)
        self.wing_span = wing_span

class Flying:
    def fly(self):
        print(f"{self.name} 正在飛翔!")

class Eagle(Bird, Flying):
    def hunt(self):
        print(f"{self.name} 正在捕獵小動物!")

# ===== 園區管理 =====
class Zoo:
    def __init__(self, name):
        self.name = name
        self.animals = []

    def add_animal(self, animal):
        self.animals.append(animal)
        print(f"✅ 已將 {animal.name} 加入 {self.name} 園區")

    def show_all_animals(self):
        print(f"=== {self.name} 動物園清單 ===")
        for a in self.animals:
            a.info()

# ===== 測試 =====
zoo = Zoo("台北動物園")

leo = Lion("Leo", 5, "Lion", "金色")
eddie = Eagle("Eddie", 3, "Eagle", 2.0)

zoo.add_animal(leo)
zoo.add_animal(eddie)

zoo.show_all_animals()

leo.roar()
eddie.fly()
eddie.hunt()
leo.feed(10)
eddie.feed(20)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251007/20164721fH0pIYsCXk.png

來說明一下這題實戰演練,我用了什麼重點語法:

這題主要透過「多層繼承」讓動物能一層層細分(例如 Animal → Mammal → Lion),同時用「多重繼承」讓部分動物擁有額外能力(例如會飛、會游泳),

展示不同父類別的功能如何整合在一起。

Animal 類別裡,我用了「私有屬性」與「私有方法」(以雙底線開頭),
確保健康值這類重要資料不會被外部直接修改;
子類別則透過 super() 呼叫父類別的建構子,確保初始化過程完整。

最後的 Zoo 類別運用了「物件組合」,以清單(list)管理多個動物實例,
結合前面學到的繼承概念,實現出一個有層次又安全的動物園系統。

學會了嗎?今天的內容也是相當不輕鬆!

結語

今天的主題其實就在講一件事——

如何讓程式更像現實世界一樣,有層次、有角色、有界線。

多層繼承讓「關係」能延續下去,多重繼承讓「能力」能靈活組合,
而私有屬性與方法,則是替物件劃出安全的界線。

在今天的實戰演練「動物園管理系統」裡,我們不只是寫出能運作的程式,
而是學會用程式去思考結構與責任——

誰該繼承誰、誰能做什麼、哪些事情該保密,這就是物件導向的精神。

當你開始用「關係」的角度看程式,
你就不再只是寫程式的人,而是設計系統的人


時間真的過得超快,轉眼間就進入第 23 天了。
每天花幾個小時整理筆記、設計練習題、把觀念寫成白話,

一開始真的很不習慣,甚至覺得有點「硬擠」。
但慢慢地,我發現這已經變成生活的一部分。

早上起床第一件事是打開 iThome 開始撰寫今天要介紹的內容,
睡前最後一件事是再檢查一遍稿子有沒有哪裡可以更清楚。

這段學習的過程,就像寫程式一樣 ——剛開始會卡、會亂、會懷疑自己,

但當你每天都多前進一點點,
回頭看時,會發現自己早就比想像中強大許多。

再撐一下,我們就要迎來最後一週。
讓我們繼續一起,把這段旅程寫得漂亮收尾吧!!

/images/emoticon/emoticon42.gif


上一篇
【Day22】讓物件變得更聰明!物件互動與繼承的實戰演練
下一篇
【Day24】模組與套件:能拆能組又能重複使用!
系列文
Python 小白的逆襲:30 天從零到能教人的精華筆記,寫給迷惘的你與當年的我自己!24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言