C 包含 A、B 共用的方法。D 是 SDK 最終類(final),不可繼承/修改。A extends C,B extends D,但 B 也需要 C 的方法 → Java 不支持多重繼承。public class B extends D {
// 1. 定義內部類繼承 C,獲得 C 的所有非私有方法
private class InnerC extends C {
// 可按需重寫或擴展 C 的方法
}
// 2. 持有內部類實例
private final InnerC innerC = new InnerC();
// 3. 對外暴露委託方法(門面模式)
public void methodFromC() {
innerC.methodFromC(); // 轉發調用
}
// 若 C 方法較多,可讓 B 實現接口,內部類實現該接口,減少樣板代碼
}
| 方案 | 優點 | 缺點 |
|---|---|---|
| 內部類繼承 C + 委託 | 繞過 final 限制;封裝性好;可控制暴露哪些方法 | 需手寫委託方法(可用 IDE 生成/ Lombok @Delegate) |
| 實現接口 + 默認方法 (Java 8+) | 無需內部類;接口默認方法提供實現 | 要求 C 改為接口,或提取公共接口;默認方法無法訪問實例狀態 |
| 組合:持有 C 實例 (非繼承) | 最鬆耦合;C 可為 final | 同樣需委託;若 C 有 protected 成員需子類訪問則不行 |
@RequiredArgsConstructor
public class B extends D {
@Delegate(types = C.class) // 自動將 C 的公共方法委託給 innerC
private final C innerC = new C(); // 或 new InnerC()
}
編譯後 Lombok 會為 B 生成所有 C 公共方法的轉發調用,極大減少樣板代碼。
C 實現接口,B 通過組合實現同一接口。D 也是外部類,B 可實現目標接口,內部持有 D 與 C 實例,雙向適配。Activity、Fragment 等最終類不可繼承,需複用邏輯類。