C# 不支援多重繼承。當 ParentA、ParentB 皆繼承 Parent 並覆寫 ApplyEditable(),且含有大量重複程式碼時,無法直接提取共同基類。
BaseC (組合物件)。IBaseCAction 宣告需多型的方法 (ApplyEditable)。ChildA, ChildB) 實作介面,提供差異化實作。Parent 持有 BaseC 實例,建構時注入 this (實作介面的子類別)。Parent (抽象基類) │ ├─ BaseC (組合:共同邏輯) ← 持有 IBaseCAction 參考 │ ├─ ChildA : Parent, IBaseCAction → 實作 ApplyEditable() └─ ChildB : Parent, IBaseCAction → 實作 ApplyEditable()
// 1. 介面定義需多型的操作
public interface IBaseCAction
{
void ApplyEditable();
}
// 2. 共同邏輯封裝於 BaseC
public class BaseC
{
private readonly IBaseCAction _action;
public BaseC(IBaseCAction action) { _action = action; }
public void CommonMethod()
{
// 共同流程...
_action.ApplyEditable(); // 委託給具體子類別
// 共同流程...
}
}
// 3. 抽象基類 Parent 持有 BaseC
public abstract class Parent
{
protected BaseC BaseC { get; private set; }
protected Parent() { } // 由子類別建構時初始化
}
// 4. 具體子類別
public class ChildA : Parent, IBaseCAction
{
public ChildA() { BaseC = new BaseC(this); }
public void ApplyEditable() { /* ChildA 專屬邏輯 */ }
}
public class ChildB : Parent, IBaseCAction
{
public ChildB() { BaseC = new BaseC(this); }
public void ApplyEditable() { /* ChildB 專屬邏輯 */ }
}
若僅有一個方法需多型,可簡化為:
public class BaseC
{
public Action ApplyEditable { get; set; } // 委派
public void CommonMethod() { ApplyEditable?.Invoke(); }
}
// 子類別建構時:BaseC = new BaseC { ApplyEditable = this.MyImplementation };
| 方案 | 優點 | 缺點 |
|---|---|---|
| 介面 | 型別安全、支援多方法、IDE 導航、契約清晰 | 稍顯繁瑣 |
| 委派 | 輕量、函數式風格、單一方法極簡 | 無介面契約、難以批次實作、序列化/反射較弱 |
「組合優於繼承」是經典設計原則。透過 BaseC 封裝共性、IBaseCAction 定義差異點、子類別建構時注入 this,在單繼承語言中優雅實現「多重繼承」語意,同時保持低耦合、高內聚。