核心定義對比
| 維度 | 介面 | 抽象類別 |
| 本質 | 契約/行為規範 (Can-Do) | 實體部分實作 (Is-A) |
| 繼承 | 多重實作 | 單一繼承 |
| 成員 | 僅方法/屬性/事件/索引子簽章 (C# 8+ 可有預設實作) | 可含欄位、建構函式、完整實作、存取修飾詞 |
| 版本演進 | 極難修改 (破壞實作) | 較易新增非破壞性成員 |
| 適用對象 | 跨層級、無關類別共享行為 | 關聯緊密、共享核心邏輯的類別階層 |
設計原則:介面隔離與依賴倒置
- 介面隔離原則 (ISP):介面應盡量小、單一職責,避免「胖介面」強迫實作類別實作不需的方法。
- 依賴倒置原則 (DIP):高層模組依賴抽象 (介面/抽象類別),而非具體實作。
實戰案例:飛行汽車
❌ 錯誤設計:介面堆疊導致雜交
interface ICar { string Wheels { get; } void Move(); }
interface IFlyable { void Fly(); }
// 強迫多重實作介面,語意模糊:它是車?還是飛機?
class FlyCar : ICar, IFlyable { ... }
✅ 正確設計:抽象類別定義核心,介面擴充行為
// 核心實體抽象:車「本質上」能移動
public abstract class Car : IMovable
{
public abstract string Wheels { get; set; }
public virtual void Move() => Console.WriteLine($"{Wheels}輪車行駛中");
}
// 擴充行為介面
public interface IFlyable { void Fly(); }
// 具體實作:飛行汽車「是一種」車,且「能」飛
public sealed class FlyCar : Car, IFlyable
{
public override string Wheels { get; set; }
public void Fly()
{
base.Move(); // 先跑一段
Console.WriteLine($"{Wheels}輪汽車起飛!");
}
}
.NET Framework 實例
Control 繼承 Component (抽象類別),實作 IDisposable, IComponent, ISynchronizeInvoke 等介面。
Stream 為抽象類別,定義核心 Read/Write/Seek,衍生 FileStream, MemoryStream, NetworkStream;CanRead/CanSeek/CanWrite 屬性讓執行期檢查能力,避免 NotSupportedException。
決策指南
- 需要跨不相關類別共享行為 → 介面
- 需要提供預設實作/共享狀態給緊密相關的子類別 → 抽象類別
- 需要版本彈性 (未來可能新增成員) → 抽象類別 (或 C# 8+ 介面預設實作)
- 需要多重「是一種」關係 → 只能用介面 (C# 不支援多重類別繼承)
- 最佳實踐:抽象類別實作介面,子類別繼承抽象類別 (如
Car : IMovable)