
類別是一個基礎的物件導向設計(Object-Oriented Programming, OOP),是一種以物件為中心的編程範式,強調模擬現實世界的實體與行為。類別將資料(屬性)和行為(方法)整合在一起,方便定義和操作不同的物件實例。
現在 ES6 標準化後,開發者可以使用更直觀的 class 語法來實現物件導向設計,簡化類別定義和繼承,提升程式結構性。
class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    speak() {
        console.log(`嗨!我的名字是${this.name},我今年${this.age}歲。`);
    }
}
const person = new Person('阿毛', 18);
person.speak(); // 嗨!我的名字是阿毛,我今年18歲。
類別的繼承,允許子類別(subclass)繼承父類別(superclass)的屬性和方法。子類別可以重寫父類別的方法,或是擴展新功能。
class Employee extends Person {
    position: string;
    constructor(name: string, age: number, position: string) {
        super(name, age); // 呼叫父類別的建構子
        this.position = position;
    }
    introduce() {
        console.log(`我是${this.name},是${this.position}。`);
    }
}
const employee = new Employee('阿毛', 18, '前端工程師');
employee.speak(); // 嗨!我的名字是阿毛,我今年18歲。
employee.introduce(); // 我是阿毛,是前端工程師。
子類別中重新定義從父類繼承來的方法,取代父類的實現。雖然不寫 override 也不會有問題,但有寫的話,會幫你校正拼字錯誤。
class Ironman extends Person {
    override speak() {
        console.log(`${this.name}正在努力撰寫鐵人賽文章...`);
    }
}
const ironman = new Ironman('阿毛', 18);
ironman.speak(); // 阿毛正在努力撰寫鐵人賽文章...
TypeScript 提供了一個建構子參數的簡寫形式來直接定義和初始化類別的屬性。只需在建構子的參數前加上下面的修飾詞,便可簡化屬性宣告和賦值的過程。
class Person {
    // 通過修飾詞簡化原本的寫法
    constructor(public name: string, public age: number) {}
    speak() {
        console.log(`嗨!我的名字是${this.name},我今年${this.age}歲。`);
    }
}
const person = new Person('阿毛', 18);
person.speak(); // 嗨!我的名字是阿毛,我今年18歲。
public 修飾詞是 TypeScript 的預設設定,表示屬性或方法可以在任何地方被訪問,不寫的話預設就是 public。
class Person {
    constructor(public name: string, public age: number) {}
    public speak() {
        console.log(`嗨!我的名字是${this.name},我今年${this.age}歲。`);
    }
}
protected 修飾詞表示屬性或方法只能在類別內部及其子類別中被訪問,而不能在類別外部被訪問。
class Person {
    constructor(protected name: string, protected age: number) {}
    protected getInfo() {
        return `嗨!我的名字是${this.name},我今年${this.age}歲。`;
    }
    speak() {
        console.log(this.getInfo());
    }
}
class Ironman extends Person {
    write() {
        // this.name 一樣可以正常使用
        console.log(`${this.name}正在努力撰寫鐵人賽文章...`);
    }
}
const ironman = new Ironman('阿毛', 18);
ironman.speak(); // 嗨!我的名字是阿毛,我今年18歲。
ironman.write(); // 阿毛正在努力撰寫鐵人賽文章...
// Error: 下面這三個都是受保護屬性,只可從類別 'Person' 及其子類別中存取。
// console.log(ironman.name);
// console.log(ironman.age);
// ironman.getInfo();
private 修飾詞表示屬性或方法只能在類別內部訪問,無法在子類別或外部使用。
class Person {
    constructor(
        protected name: string,
        protected age: number,
        private idCard: string,
    ) {}
}
class Ironman extends Person {
    write() {
        // this.name 一樣可以正常使用
        console.log(`${this.name}正在努力撰寫鐵人賽文章...`);
    }
    getSuperclassPrivate() {
        // Error: 'idCard' 是私用屬性,只可從類別 'Person' 中存取。
        // return this.idCard;
    }
}
const ironman = new Ironman('阿毛', 18, 'A123456789');
ironman.write();    // 阿毛正在努力撰寫鐵人賽文章...。
// Error: 'idCard' 是私用屬性,只可從類別 'Person' 中存取。
// console.log(ironman.idCard);
readonly 修飾詞使屬性只能在初始化時賦值,之後不可更改。這提供了一種保護機制,防止屬性被意外修改。
class Ironman {
    constructor(public readonly title: string) {}
    showTitle() {
        console.log(`鐵人賽文章標題:「${this.title}」`);
    }
}
const ironman = new Ironman('TypeScript 完全指南:從語法基礎到高級功能的系統學習');
ironman.showTitle();  // 鐵人賽文章標題:「TypeScript 完全指南:從語法基礎到高級功能的系統學習」
// Error: 因為 'title' 為唯讀屬性,所以無法指派至 'title'。
// ironman.title = '我想變更標題';