在面向對象領域,抽象類型是對一組「看似不同、本質相同」具體概念的抽象提煉。它定義了一組固定的行為契約,但將具體實現延遲到衍生類。關鍵價值:
Java 提供兩種定義抽象類型的機制:abstract class 與 interface。兩者語法相似、可互換,但設計意圖截然不同,選型錯誤會導致架構腐化。
| 特性 | abstract class | interface (Java 7) | interface (Java 8+) |
|---|---|---|---|
| 繼承/實現關鍵字 | extends | implements | |
| 多重實現 | 單繼承 | 多實現 | |
| 建構子 | 可有 | 無 | 無 |
| 實例欄位 | 任意修飾符 | 無 | 無 |
| 靜態欄位 | 任意 | 隱含 public static final | 同左 |
| 實例方法 | 可抽象/具體 | 隱含 public abstract | 可 default 具體實現 |
| 靜態方法 | 可有 | 無 | 可 static 具體實現 |
| 私有方法 | 可有 | 無 | Java 9+ 支援 private |
abstract class 表達 "is-a"(是一種)關係:子類型在概念本質上屬於父類型範疇。
interface 表達 "like-a"(像一種/具備...能力)關係:實現類只需滿足契約,本質可完全不同。
// 領域概念:門(核心行為:開/關)
abstract class Door {
abstract void open();
abstract void close();
}
// 能力契約:報警(非門的本質行為)
interface Alarm {
void alarm();
}
// 具體實現:防盜門 = 是一門 + 具備報警能力
class AlarmDoor extends Door implements Alarm {
void open() { ... }
void close() { ... }
void alarm() { ... }
}
// ❌ 將「報警」強行塞入 Door 抽象類
abstract class Door {
abstract void open();
abstract void close();
abstract void alarm(); // 污染了 Door 的核心職責
}
// ❌ 或用介面混雜兩個概念
interface Door {
void open();
void close();
void alarm(); // 實現類被迫實現不相關行為
}
後果:依賴「開關門」的模組因「報警」變更而重編譯/部署;違反「單一職責」、「介面隔離」、「依賴倒置」。
abstract class(提供預設實現、保護式欄位、建構子邏輯)。interface(Java 單繼承限制)。abstract class。interface。interface(JDBC Driver、Logger、Parser 等標準擴展點)。interface Loggable {
default void log(String msg) {
System.out.println("[" + LocalDateTime.now() + "] " + msg);
}
}
InterfaceA.super.method())。interface Collection {
static List of(E... elements) { ... }
}
interface Complex {
default void doA() { helper(); }
default void doB() { helper(); }
private void helper() { ... } // Java 9+
}
interface Constants { int MAX = 100; } → 實現類隱性繼承常量,造成命名空間污染、二進制相容性陷阱。
✅ 改用 final class Constants 或 enum。
介面無建構子、無實例狀態、無私有模板邏輯。
✅ 抽象類定義骨架,介面定義擴展點。
抽象類是「部分實現的共享骨架」,介面是「行為契約」。兩者互補,非替代。
✅ 領域模型核心骨架用抽象類,跨領域能力用介面。
| 場景 | 推薦 | 理由 |
|---|---|---|
| 領域核心實體骨架(如 Animal、Account、Vehicle) | abstract class | 共享狀態/邏輯、強制 is-a、建構子約束 |
| 跨領域能力(Serializable、Comparable、Runnable、Cloneable) | interface | like-a、多實現、無狀態 |
| SPI 擴展點(Driver、Provider、Strategy) | interface | 標準契約、零依賴、動態發現 |
| 需要預設實現且無狀態(工具行為) | interface + default | 演進相容、避免抽象類膨脹 |
| 模板方法模式(算法骨架固定、步驟可變) | abstract class | 封裝演算法結構、控制子類擴展點 |
記住:abstract class 定義「它是什麼」,interface 定義「它能做什麼」。準確把握領域本質,架構才能經得起變化考驗。