整理 Effective Java 書中 Item 20: Prefer interfaces to abstract classes 心得筆記

主旨

Java 提供兩種方式定義「可以有多個實作」的類型:介面(interface)和抽象類別(abstract class)。在 Java 8 引入 default methods 之後,兩者都能提供方法實作。但總體來說,介面更靈活、延伸性更好,也比較不會限制使用者的設計。本章重點就是告訴你:大多數情況下,請選擇介面。

劃重點:介面 vs 抽象類別 差在哪

功能介面(interface)抽象類別(abstract class)
支援多重繼承✅ 可以實作多個介面❌ 只能繼承一個抽象類別
default method✅(Java 8 之後)
可 retrofitting(套用到舊類別)✅ 很容易加上❌ 幾乎不可能
支援 mixin 類型(混合功能)
適合建構非階層型態系統
可定義實體欄位❌(僅 static final)
限制少、彈性高❌ 限制多

🌟 說人話的版本:

  • 如果你只是要定義「這個東西能做某件事」→ 用 介面
  • 如果你想封裝共用邏輯,又不能靠 default method 完成 → 可考慮抽象類別

淺顯範例:歌手與創作人

假設我們要設計兩種角色:

public interface Singer {
    AudioClip sing(Song s);
}

public interface Songwriter {
    Song compose(int chartPosition);
}

某些人可能兩者兼具,我們就可以這樣定義:

public interface SingerSongwriter extends Singer, Songwriter {
    AudioClip strum();
    void actSensitive();
}

這就是介面的威力:多型、非階層化、自由組合。如果我們用抽象類別,就完全做不到這點。

搭配骨架實作(skeletal implementation)更強大

介面可以搭配「骨架實作類別」使用,把通用邏輯寫在抽象類別裡,讓使用者可以選擇要不要繼承這個骨架。

這是「Template Method」設計模式的一種常見應用。

static List<Integer> intArrayAsList(int[] a) {
    return new AbstractList<>() {
        public Integer get(int i) { return a[i]; }
        public Integer set(int i, Integer val) {
            int old = a[i];
            a[i] = val;
            return old;
        }
        public int size() { return a.length; }
    };
}

這段程式碼是一個將 int[] 包裝成 List<Integer> 的實作。它用到了骨架類別 AbstractList,大幅減少實作 List 需要寫的程式碼量。

真實世界範例補充

Java Collections Framework 裡幾乎每個核心介面都有搭配的骨架類別:

  • CollectionAbstractCollection
  • ListAbstractList
  • SetAbstractSet
  • MapAbstractMap

開發者可以選擇:

  • 直接實作介面(自由)
  • 繼承骨架類別(省事)

這種設計既不會強迫使用者繼承某個 class,又提供擴充的便利性,是 Java 設計中非常值得學習的一點。

小提醒:介面還是有限制

  • 不能加實體欄位
  • 無法提供 equals()hashCode() 等 Object 方法的 default 實作
  • 無法對你無法控制的介面加 default method(例如別人寫的)
  • 介面 + default method ≠ 萬能 → 有些功能還是得靠骨架實作來補足

小結

個人是蠻享受這種方式進行開發的,要設計一個可擴充、多實作的型別時,請優先考慮介面:

  • ✅ 可多重實作
  • ✅ 支援 mixin 與非階層型態
  • ✅ 可 retrofitting 到舊類別
  • ✅ 搭配 default method、骨架實作靈活又強大

只有在需要共用狀態或 default method 做不到時,才考慮使用抽象類別。否則,介面就是你的第一選擇。

介面讓你自由組合;
抽象類別讓你綁死一整包。
能選介面,就別選抽象類別。