Java 單一繼承限制(extends 僅能指定一個父類別)有時會限制領域建模。透過內部類,一個類別可同時繼承/實現多個父類別或介面,實現邏輯上的多重繼承。本文以雙抽象類別合成為例,展示匿名內部類實現第二父類別的核心模式與應用場景。
abstract class A {
abstract void methodA();
}
abstract class B {
abstract void methodB();
}
class C extends A {
@Override
void methodA() {
System.out.println("extends A's method");
}
B getB() {
return new B() { // 匿名內部類繼承 B
@Override
void methodB() {
System.out.println("extends B's method");
}
};
}
}
public class MultiImplementation {
public void doA(A a) { a.methodA(); }
public void doB(B b) { b.methodB(); }
public static void main(String[] args) {
MultiImplementation mi = new MultiImplementation();
C c = new C();
mi.doA(c); // C 本身是 A
mi.doB(c.getB()); // 透過內部類實例是 B
}
}
extends A's method
extends B's method
C (extends A)
└── 內部類 (extends B) ← 匿名類別,隱含持有外部 C 實例參考
C 直接繼承 A,滿足 doA(A) 需求。getB() 回傳一個繼承 B 的匿名內部類實例,滿足 doB(B) 需求。兩者邏輯上構成「C 同時是 A 和 B」。
| 特性 | 說明 | ||
|---|---|---|---|
| 外部類別存取 | 內部類可直接存取 C 的所有成員(含 private),透過隱含 C.this 參考 | ||
| 實例關聯 | 每個 C 實例擁有獨立的內部類實例,生命週期綁定 | ||
| 型別轉換 | C 可轉型為 A;getB() 回傳值可轉型為 B;但 C 無法直接轉型為 B | ||
| 方法覆寫 | 內部類可覆寫 B 的抽象方法,也可覆寫 Object 方法 |
| 方案 | 優點 | 缺點 | 適用性 |
|---|---|---|---|
| 實作多個介面 | 標準、無狀態衝突、編譯期檢查 | 無程式碼重用、無建構子鏈 | 行為契約、無狀態共享 |
| 抽象類別 + 內部類 | 可重用程式碼/狀態、支援建構子邏輯 | 結構較複雜、內部類持有外部參考 | 需繼承具體實作的多重角色 |
| 組合/委派 | 鬆耦合、靈活替換、符合設計原則 | 樣板代碼多、需轉發呼叫 | 大多數實務場景首選 |