🚀 物件導向程式設計 (OOP):Option D 學習筆記
歡迎來到物件導向程式設計的世界!別擔心,這個名字聽起來雖然深奧,但它其實是一種非常強大的程式碼組織方式,能讓大型軟體專案變得更好管理、更容易重用,且更易於維護。
在本章中,我們將不再把程式視為一長串的指令清單(程序導向程式設計),而是將其視為一組互相作用的「事物」或物件 (Objects)。這種思維方式是現代軟體開發的核心,因此對於你的 IB 考試和未來的程式設計之路來說,精通它是至關重要的!
1. 基礎:類別 (Classes) 與物件 (Objects)
類別與物件有什麼區別?
這是 OOP 最關鍵的起點。你必須弄清楚「藍圖」與「根據藍圖蓋好的房子」之間的差別。
1.1 類別 (Class):藍圖
- 類別 (Class) 是一個範本、一張藍圖,或是對某種特定物件的定義。
- 它定義了該類別的物件會包含哪些資料(屬性)以及可以執行哪些動作(方法)。
- 類比:就像一個餅乾模具。它定義了形狀,但它本身並不是餅乾。
1.2 物件 (Object):實例 (Instance)
- 物件 (Object) 是類別的真實、具體實例。
- 它是根據類別定義在電腦記憶體中建立出來的。
- 從類別建立物件的過程稱為實例化 (Instantiation)。
- 類比:使用模具烤出來的一片片餅乾。每一片餅乾都是一個獨立的物件。
範例:
如果我們有一個名為 Car(汽車)的類別,我們可以從中建立多個物件(實例):
- 物件 1:myCar(紅色、時速 60 英里、Model X)
- 物件 2:yourCar(藍色、時速 85 英里、Model Y)
重點總結:
類別決定了結構;物件則是程式中真實運作的實體。
2. 物件的剖析:狀態與行為
OOP 中的每個物件都由兩部分定義:
2.1 狀態 (State / Attributes / Data)
狀態定義了物件所擁有的特徵或資料欄位。這些通常被稱為屬性 (Attributes) 或實例變數 (Instance variables)。
- 範例:對於一個 Dog(狗)物件,屬性可能包含:顏色、品種和年齡。
2.2 行為 (Behavior / Methods)
行為定義了物件可以做什麼。這些是透過方法 (Methods)(在類別內定義的函式)來實現的。
- 範例:對於一個 Dog(狗)物件,方法可能包含:bark()(吠叫)、run()(奔跑)或 eat()(進食)。
2.3 建構子 (Constructors)
建構子 (Constructor) 是一種特殊的方法,當物件被實例化時會自動呼叫。它的主要工作是設定新物件的初始狀態(初始化屬性)。
- 類比:當你購買一支新手機(實例化物件)時,建構子就是設定過程——設定語言、時區和初始配置(狀態)。
2.4 訊息傳遞 (Message Passing)
物件之間透過傳遞訊息 (Messages) 進行互動。在 OOP 術語中,「傳遞訊息」是指呼叫另一個物件的方法。
- 範例:如果物件 A 需要物件 B 執行某個動作,物件 A 就會呼叫物件 B 的方法。
常見錯誤:別把屬性和方法搞混了。屬性是名詞(資料);方法是動詞(動作)。
3. OOP 的四大支柱
這四大原則是物件導向程式設計的骨幹,理解它們對於 HL 考試至關重要。
3.1 封裝 (Encapsulation)
定義:
封裝 (Encapsulation) 是將資料(屬性)和操作該資料的方法綑綁在一起,形成一個單一單位(類別),並限制對該物件部分組件的直接存取。
類比:想像一顆藥囊。藥物(資料)被安全地包在殼(類別)內。你只能透過殼上的指示(方法)與藥物互動,例如「配水吞服」。
資訊隱藏 (Information Hiding):
封裝的一個關鍵面向是資訊隱藏。我們透過將屬性設為私有 (Private) 來保護物件的內部狀態,然後提供公開的方法(稱為 **Getter** 和 **Setter**,或稱存取器與修改器)來讀取或修改私有資料。
- 為什麼要這麼做? 這樣可以防止外部程式碼不小心破壞資料。如果客戶的銀行餘額不能為負數,'withdraw'(提款)方法可以在變更私有餘額屬性之前檢查金額是否足夠。
重點複習:
封裝 = 綑綁 + 保護。
它確保了物件的內部運作機制是隱密的,且只能透過受控的方式進行存取。
3.2 繼承 (Inheritance)
定義:
繼承 (Inheritance) 是類別間獲取彼此屬性(屬性和方法)的機制。這實現了程式碼的重用,並建立了層級關係。
類比:族譜。子類別繼承了父類別的特徵。子類別不需要重新定義繼承來的特徵,但可以新增或修改既有的內容。
術語:
- 原始類別稱為父類別 (Parent Class)、超類別 (Superclass) 或基底類別 (Base Class)。
- 新類別稱為子類別 (Child Class)、衍生類別 (Subclass) 或衍生類別 (Derived Class)。
好處:
繼承遵循 DRY 原則:Don't Repeat Yourself(不要重複自己)。如果 Dog 和 Cat 都需要 eat() 方法和 age 屬性,我們只需在 Animal 超類別中定義一次,兩個子類別就能共同繼承它們。
3.3 多型 (Polymorphism)
如果一開始覺得這部分很難也別擔心——多型(意思是「多種形式」)的核心在於靈活性和定義標準化介面。
定義:
多型 (Polymorphism) 允許將不同類別的物件視為同一類型的物件(它們的超類別),並讓單一操作(方法呼叫)根據物件實際所屬的類別產生不同的行為。
類比:「啟動引擎」的功能。無論你對「柴油卡車」物件還是「混合動力車」物件呼叫「啟動引擎」,所需的動作是一樣的(啟動引擎),但底層的執行細節(引擎實際啟動的方式)卻截然不同。
關鍵機制:方法覆寫 (Method Overriding)
這是 IB 中最常見的多型形式。如果子類別擁有與超類別相同的方法簽章(名稱和參數),子類別的版本將會取代超類別的版本執行,這稱為方法覆寫 (Method Overriding)。
- 範例: 超類別 Animal 有一個 makeSound() 方法,輸出「噪音」。子類別 Cow 覆寫了 makeSound() 輸出「哞」。當你對一個 Cow 物件呼叫 makeSound() 時,你會得到「哞」。
3.4 抽象 (Abstraction)
定義:
抽象 (Abstraction) 是只向外界展示必要資訊,同時隱藏背景實作細節的過程。它專注於物件「做什麼」,而不是它是「如何達成」的。
類比:開車。你與油門和方向盤互動(必要的介面)。你不需要理解內燃機、燃油噴射和差速齒輪的複雜物理原理也能開車。這些複雜的細節都被隱藏(抽象化)了。
抽象 vs. 封裝:
它們相關但截然不同:
- 封裝是一種機制(使用私有變數和方法),確保實作過程整潔且安全。
- 抽象是一種概念或目標——它呈現給使用者的是簡化且必要的觀點。
你知道嗎?
抽象正是為什麼程式設計師可以使用複雜函式庫(例如圖形函式庫)而無需閱讀數千行原始碼的原因。他們只需要知道抽象介面所定義的必要方法和參數即可。
🎉 結論與複習
你現在已經掌握了 OOP 的核心原則!記住,OOP 的設計初衷就是模擬現實世界,這就是為什麼當你開始以現實生活中的實體來思考時,類別、物件和繼承結構會變得非常直觀。
這裡有一個最終的記憶口訣,幫助你記住四大支柱:
A P I E (抽象 Abstraction, 多型 Polymorphism, 繼承 Inheritance, 封裝 Encapsulation)
快速概念檢查清單:
- 類別 (Class) 是藍圖,定義了屬性(狀態)和方法(行為)。
- 物件 (Object) 是類別的實例,透過建構子 (Constructor) 建立。
- 封裝 (Encapsulation) 隱藏資料(使用私有屬性)並透過公開方法提供受控的存取權。
- 繼承 (Inheritance) 允許子類別重用並擴充超類別的程式碼。
- 多型 (Polymorphism) 允許物件對相同的方法呼叫做出不同的反應(通常透過方法覆寫)。
- 抽象 (Abstraction) 只向使用者展示必要的功能,隱藏複雜性。
繼續練習在程式碼中定義這些概念。你一定沒問題的!