TypeScript 中的類別

TypeScript 中的類別

本文解釋了 TypeScript 中的類別。

YouTube Video

TypeScript 中的類別

TypeScript 的類別基於 JavaScript 的 ES6 類別,並提供類型註解和訪問修飾符等額外功能。這使您能利用面向對象編程的概念,同時確保更強健和清晰的類型安全性。

以下是 TypeScript 中類別的基本用法和功能解釋。

基本類別定義

 1class Person {
 2    name: string;  // Member variable
 3    age: number;   // Member variable
 4
 5    // Constructor
 6    constructor(name: string, age: number) {
 7        this.name = name;
 8        this.age = age;
 9    }
10
11    // Method
12    greet(): void {
13        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
14    }
15}
16
17const person = new Person("Alice", 25);
18person.greet();  // Hello, my name is Alice and I am 25 years old.
  • nameage 是類別的屬性(成員變量)。
  • constructor 是創建類別實例時調用的方法,該方法接收參數並將值分配給屬性。
  • greet 是類別的一個方法,其類型為 void,表明它沒有返回值。

訪問修飾符

在 TypeScript 中,您可以使用訪問修飾符(publicprivateprotected)來控制對類別屬性和方法的訪問。

public

默認情況下,所有屬性和方法都是 public 的。這意味著它們可以從類別外部訪問。

 1class Animal {
 2    public species: string;
 3
 4    constructor(species: string) {
 5        this.species = species;
 6    }
 7
 8    public makeSound(): void {
 9        console.log(`${this.species} makes a sound.`);
10    }
11}
12
13const animal = new Animal("Dog");
14console.log(animal.species);  // Dog
15animal.makeSound();           // Dog makes a sound.
  • species 屬性和 makeSound 方法被宣告為 public,可以從類別外部存取。

private

使用 private 修飾符可防止從類別外部訪問屬性或方法。

 1class Car {
 2    private brand: string;
 3
 4    constructor(brand: string) {
 5        this.brand = brand;
 6    }
 7
 8    public getBrand(): string {
 9        return this.brand;
10    }
11}
12
13const car = new Car("Toyota");
14// console.log(car.brand);  // Error: 'brand' is private and cannot be accessed.
15console.log(car.getBrand());  // Toyota
  • brand 屬性被宣告為 private,所以無法從類別外部存取。
  • 使用 private 修飾詞隱藏屬性可以實現資料封裝。

protected

protected 修飾符限制從類別外部訪問,但允許在子類(派生類別)中訪問。

 1class Vehicle {
 2    protected model: string;
 3
 4    constructor(model: string) {
 5        this.model = model;
 6    }
 7}
 8
 9class Truck extends Vehicle {
10    public getModel(): string {
11        return this.model;
12    }
13}
14
15const truck = new Truck("Ford F-150");
16console.log(truck.getModel());  // Ford F-150
17
18// console.log(truck.model);
19// Error: Property 'model' is protected and only accessible within class 'Vehicle' and its subclasses.
  • model 屬性被宣告為 protected,因此無法從類別外部存取,但可以從子類別存取。

Getter 和 Setter

在 TypeScript 中,您可以使用 getset 關鍵字定義 Getter 和 Setter,以獲取和設置屬性值。

 1class Employee {
 2    private _salary: number;
 3
 4    constructor(salary: number) {
 5        this._salary = salary;
 6    }
 7
 8    // Getter
 9    get salary(): number {
10        return this._salary;
11    }
12
13    // Setter
14    set salary(newSalary: number) {
15        if (newSalary > 0) {
16            this._salary = newSalary;
17        } else {
18            console.log("Salary must be positive.");
19        }
20    }
21}
22
23const employee = new Employee(50000);
24console.log(employee.salary);  // 50000
25employee.salary = 60000;
26console.log(employee.salary);  // 60000
27employee.salary = -100;        // Salary must be positive.
  • 在這個範例中,對 salary 屬性使用 getter 和 setter 來控制外部存取與更新。setter 會執行驗證以防止負值,如果提供了無效的值則顯示警告訊息。

繼承

在 TypeScript 中,類別可以被繼承。使用 extends 關鍵字,您可以從父類別繼承功能。

 1class Animal {
 2    constructor(public name: string) {}
 3
 4    public move(): void {
 5        console.log(`${this.name} is moving.`);
 6    }
 7}
 8
 9class Bird extends Animal {
10    public fly(): void {
11        console.log(`${this.name} is flying.`);
12    }
13}
14
15const bird = new Bird("Sparrow");
16bird.move();  // Sparrow is moving.
17bird.fly();   // Sparrow is flying.
  • 在這個範例中,Bird 類別繼承自 Animal 類別,因此可以使用 Animalmove 方法。此外,它定義了自己的 fly 方法,在繼承父類別功能的同時新增新功能。

抽象類別

抽象類別(abstract)不能直接實例化,並用作模板以在子類別中提供具體實現。

 1abstract class Shape {
 2    abstract getArea(): number;
 3
 4    public describe(): void {
 5        console.log("This is a shape.");
 6    }
 7}
 8
 9class Circle extends Shape {
10    constructor(private radius: number) {
11        super();
12    }
13
14    public getArea(): number {
15        return Math.PI * this.radius * this.radius;
16    }
17}
18
19const circle = new Circle(5);
20console.log(circle.getArea());  // 78.53981633974483
21circle.describe();  // This is a shape.
  • 在這個範例中,Shape 被定義為抽象類別,getArea 是必須被子類別實作的抽象方法。Circle 類別繼承這個抽象類別,並實作自己用來計算圓面積的 getArea 方法。此外,像 describe 這樣的具體方法也被子類繼承作為共用功能,並可直接使用。

與介面的關係

類別可以實現介面,確保它們具有特定的屬性和方法。

 1interface Flyable {
 2    fly(): void;
 3}
 4
 5class Airplane implements Flyable {
 6    public fly(): void {
 7        console.log("The airplane is flying.");
 8    }
 9}
10
11const airplane: Flyable = new Airplane();
12airplane.fly();  // The airplane is flying.
  • 在這個範例中,Flyable 介面定義了 fly 方法的規範,而 Airplane 類別則透過具體實作 fly 方法來實現此介面。如此一來,任何可以視為 Flyable 型別的物件都保證會有 fly 方法。

靜態成員

當在類別中定義靜態成員時,這些方法和屬性是隸屬於類別本身的。靜態成員可以在不實例化類別的情況下被呼叫。

 1class MathUtils {
 2    static PI: number = 3.14;
 3
 4    static add(a: number, b: number): number {
 5        return a + b;
 6    }
 7}
 8
 9console.log(MathUtils.add(10, 20)); // 30
10console.log(MathUtils.PI); // 3.14
  • 你可以使用 static 關鍵字定義靜態方法。
  • 在這個範例中,MathUtils 類別定義了一個靜態方法 add 和一個靜態屬性 PI
  • 靜態成員不屬於類別的實例,而是可以從類別本身直接呼叫。

總結

TypeScript 類別為 JavaScript 的類別功能新增了類型安全、存取修飾符和抽象類別等功能。這使得物件導向程式設計更加強大且安全。

您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。

YouTube Video