你是不是在專案越來越大時,覺得 TypeScript 的程式碼難以保持邏輯與維護呢?🤔
不用擔心,class
(類別)和 module
(模組)是你的救星!
今天我們將深入探討 TypeScript 中的物件導向程式設計,並發現如何使用 class
和 module
來建立結構化且可重用的程式碼。
從繼承、存取修飾符(access modifiers)到抽象類別(abstract class)和命名空間(namespace),你將學習到這些重要概念,幫助你提升 TypeScript 技能,打造可擴展且易於維護的應用程式。
準備來掌握這些技巧吧!💪🚀
在你對 TypeScript 型別已有的理解基礎上,這篇文章將進一步介紹 class
(類別)與 module
(模組)這兩個對於大型專案開發者至關重要的概念。
這些功能不僅與傳統的物件導向程式設計(OOP)完美契合,還透過封裝(encapsulation)和模組化(modularization)來提升程式碼的組織性與重用性,讓專案更易於維護和擴展。
在 TypeScript 的物件導向設計中,class
(類別)是用來描述物件的結構和行為的關鍵工具。它能夠將相關的屬性(properties)和方法(methods)整合在一起,讓我們能夠更直觀、模組化地組織程式碼。
繼承(inheritance)是物件導向程式設計的核心概念之一,通過它,開發者可以讓一個類別繼承另一個類別的屬性和方法。這樣做的好處是:
下面的範例展示了如何使用 class
和繼承來描述不同的動物行為。
class Animal {
name: string;
// 建構函式 constructor 用於初始化物件的 name 屬性
constructor(name: string) {
this.name = name;
}
// move 方法表示動物的移動行為
move(distanceInMeters: number): void {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) {
// 使用 super 呼叫父類別的 constructor
super(name);
}
// 覆寫父類別的 move 方法,並提供默認值
move(distanceInMeters = 5): void {
console.log("Slithering...");
super.move(distanceInMeters); // 呼叫父類別的 move 方法
}
}
在這個範例中,我們定義了一個 Animal
類別,並繼承了一個 Snake
類別:
Animal
:定義了所有動物共用的屬性 name
和方法 move
,move
方法接收距離參數,並輸出動物移動的訊息。Snake
:繼承了 Animal
的屬性和方法,並在它的 move
方法中進行了覆寫(override),增加了一個特定於蛇的行為 "Slithering...",然後呼叫了父類別的 move
方法來保持基本的移動行為。class
和繼承在實際專案中有非常廣泛的應用,特別是當專案變得越來越大時,能夠建立良好組織的程式架構是至關重要的。
透過繼承,我們可以為程式設計出一個「基礎架構」,讓各種不同的實體(如動物、交通工具、角色等)共用基礎功能,並在子類別中進行擴展或覆寫。
假設我們正在開發一個大型應用程式,這個應用程式中有多種不同的動物,每種動物的行為可能略有不同。與其為每一個動物類別重複撰寫相同的移動邏輯,我們可以使用繼承來定義一個通用的 Animal
類別,然後讓其他動物類別(如 Snake
或 Bird
)繼承這個基礎類別,並根據需要覆寫特定行為。
例如,除了蛇之外,我們還可以定義一個 Bird
類別,讓它繼承 Animal
,並覆寫 move
方法來加入飛翔的邏輯:
class Bird extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 10): void {
console.log("Flying...");
super.move(distanceInMeters);
}
}
這樣做不僅提高了程式碼的重用性,還確保了不同類別之間的行為一致性。
我們可以很輕鬆地修改父類別的邏輯,並且這些修改會自動反映到所有子類別上,減少了重複修正的工作。
隨著專案的擴展,開發者可以輕鬆新增更多的子類別或修改父類別的邏輯,而不會影響現有的程式碼。這使得應用程式能夠快速適應變化,保持穩定的基礎架構,同時也為未來的擴展提供了足夠的彈性。
TypeScript 中的 public
、private
和 protected
存取修飾符(access modifiers)為我們提供了控制類別成員可見性和訪問範圍的工具。這讓開發者可以更好地封裝(encapsulation)類別內部的資料,保護物件的狀態,並只公開必要的部分。
public
、private
和 protected
的作用public
(公開):public
成員可以在類別內、類別外以及子類別中被訪問。它是 TypeScript 的預設修飾符,若未顯式聲明,類別成員即為 public
。
private
(私有):private
成員只能在類別內部被訪問,無法從外部或子類別中直接存取。這有助於防止程式碼在無意中修改或直接操作類別的內部狀態。
protected
(受保護):protected
成員可以在類別內部和子類別中被訪問,但無法從類別外部直接存取。這在父子類別間共享資料的情境下特別有用。
以下範例展示了如何使用 private
和 public
修飾符來控制類別的成員可見性。
class Animal {
// 使用 private 將 name 屬性設為私有
private name: string;
constructor(name: string) {
this.name = name;
}
// 使用 public 讓 move 方法可以從類別外部訪問
public move(distanceInMeters: number): void {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
在這段程式碼中:
name
被設定為 private
,因此只能在 Animal
類別內被存取,無法從外部修改。move
方法是 public
,允許外部使用者呼叫並執行這個方法。存取修飾符非常適合用來保護類別內的私有資料,例如一個物件的內部狀態不應被外部隨意修改。
這樣的封裝方式可以保護應用程式免受意外的變更,同時也讓開發者更清楚哪些成員是公開的,哪些是應該保護的。
例如,在一個銀行系統中,我們可以用 private
修飾符來保護客戶的敏感資訊(如銀行賬號),只允許某些方法來處理這些資料,而不是讓外部系統直接修改它。
抽象類別(abstract class)是 TypeScript 中另一個重要的物件導向功能,它提供了一個藍圖,讓開發者能夠定義必須在子類別中實作的通用方法。
與一般類別不同,抽象類別無法直接實例化,它們只能作為其他類別的基礎。
不能實例化:抽象類別只能作為基礎類別,無法被直接用來創建物件。例如,無法直接 new Department()
,必須透過衍生類別來實作。
抽象方法:抽象方法必須在子類別中實作,抽象方法沒有具體的實作內容,只提供一個結構讓子類別來實作具體邏輯。這讓開發者能夠定義一組標準,保證所有子類別都會遵循這些規則。
以下範例展示了一個抽象類別 Department
,其中包含一個必須由子類別實作的抽象方法 printMeeting
。
abstract class Department {
// 定義部門名稱屬性,並使用建構函式進行初始化
constructor(public name: string) {}
// 普通方法,可供子類別直接使用
printName(): void {
console.log("Department name: " + this.name);
}
// 抽象方法,必須在衍生類別中實作
abstract printMeeting(): void;
}
// 衍生類別必須實作抽象方法
class ITDepartment extends Department {
constructor() {
super("IT Department");
}
printMeeting(): void {
console.log("The IT department meeting is scheduled at 10 AM.");
}
}
在這裡:
Department
是一個抽象類別,定義了 printName
方法(可直接使用),並強制要求衍生類別實作 printMeeting
方法。ITDepartment
是一個具體的類別,繼承自 Department
,並實作了 printMeeting
方法。抽象類別適合用來定義某些通用行為和結構,並要求具體的衍生類別提供實作。例如,在大型應用中,我們可以使用抽象類別來定義不同類型使用者的共同行為,像是員工和管理者的登入邏輯,然後透過不同的子類別來處理具體的角色行為。
在 TypeScript 中,module
(模組)是一個非常強大的功能,幫助開發者將程式碼組織成更小、更具模組化的部分。
模組允許開發者將程式碼分隔成不同的檔案,並透過 export
和 import
來共享類別、介面、函式等。
提升可維護性:模組可以將程式碼拆分成易於管理的部分,這樣可以避免將所有邏輯寫在同一個檔案中,從而提升程式碼的可讀性與維護性。
避免命名衝突:模組中的程式碼會被封裝起來,避免與其他模組發生命名衝突。這讓開發者可以使用相同名稱的變數或類別,而不會擔心覆蓋問題。
促進重用性:透過 export
將類別或功能從模組中導出,其他檔案可以 import
這些功能並重用,讓程式碼更具模組化。
以下範例展示了如何使用模組來分離和重用程式碼。
// 在檔案 Shape.ts 中定義 Rectangle 類別,並使用 export 將其導出
export class Rectangle {
constructor(public width: number, public height: number) {}
// 計算矩形面積的方法
area(): number {
return this.width * this.height;
}
}
// 在檔案 App.ts 中,import Rectangle 並使用
import { Rectangle } from "./Shape";
let myRectangle = new Rectangle(5, 3);
console.log(myRectangle.area()); // 輸出: 15
在這裡:
Rectangle
類別定義在 Shape.ts
檔案中,並使用 export
將其導出,允許其他模組或檔案使用。App.ts
中,我們透過 import
將 Rectangle
引入並使用它來創建矩形物件,進行面積計算。模組非常適合用來拆分大型專案,特別是在多人開發的環境中,模組化能夠讓團隊更清晰地分工和合作。
例如,你可以將專案中的每個功能區塊(如使用者管理、產品列表等)拆分為不同的模組,每個模組負責一個單一的功能,並透過 export
和 import
將功能整合到一起,這樣就能讓專案更具結構性且更易維護。
今天的程式碼寫得越好,明天的你就越輕鬆!🌟💻
所以別偷懶,繼續優化每一行程式碼吧~未來的你一定會感謝現在的自己!🚀😊