TypeScript 抽象類別 (Abstract Class)

所有的房子都是「建築物」,但世界上不存在一棟建築物就叫「建築物」。它一定會有更具體的型態,像是「公寓」、「透天」或「摩天大樓」。

在程式設計中,抽象類別就是那個概念上的「建築物」。

什麼是抽象類別?

抽象類別像是一張未完成的藍圖

  1. 不能被實例化:你不能 new 建築物(),因為它太抽象了。
  2. 作為基底:它可以被繼承。
  3. 包含抽象方法:它可以規定子類別「必須」實作哪些功能。
abstract class Animal {
  // 1. 一般方法:子類別可以直接繼承使用,不用重寫
  eat() {
    console.log('Nom nom nom...');
  }

  // 2. 抽象方法:沒有內容,子類別「必須」實作
  abstract makeSound(): void;
}

// const a = new Animal(); // 錯誤!抽象類別不能 new

實作抽象類別

當你繼承一個抽象類別時,你就像是簽了一份合約,承諾要把那些「未完成」的部分做完。

class Dog extends Animal {
  // 必須實作 makeSound,否則編譯器會報錯
  makeSound() {
    console.log('汪汪!');
  }
}

class Cat extends Animal {
  makeSound() {
    console.log('喵喵~');
  }
}

const dog = new Dog();
dog.eat(); // 繼承自 Animal
dog.makeSound(); // 自己的實作

抽象類別 vs 介面 (Interface)

這是面試必考題,也是新手最容易搞混的。

特性抽象類別 (Abstract Class)介面 (Interface)
本質是一個 Class,編譯後會有 JS 程式碼只是型別定義,編譯後完全消失
實作可以包含實作細節 (如 eat 方法)只能定義「形狀」,不能有程式碼
用途Code Reuse (程式碼共用):父類別幫你寫好一半,你寫剩下一半Contract (契約):規定你一定要有哪些屬性或方法

什麼時候用哪個?

  • 如果你有多個類別有重複的邏輯 (例如大家都要 eat),用抽象類別
  • 如果你只是想規定一個標準規格 (例如大家都要有 print() 方法,但實作方式完全不同),用介面