「抽象類」與「介面」是 C# 面向對象設計的兩大支柱,混淆二者會導致架構僵化、擴展困難。本文從語法限制、語義本質、版本控制、設計模式四個維度,建立清晰的選型決策模型。
| 特性 | 抽象類 abstract class | 介面 interface |
|---|---|---|
| 實例化 | 不可 | 不可 |
| 成員類型 | 字段、屬性、方法、事件、索引器、構造函數、運算符 | 方法、屬性、事件、索引器 (C# 8+ 默認實現)、靜態成員 (C# 8+) |
| 字段/狀態 | 支持 (實例/靜態/readonly/const) | 不支持 實例字段 (C# 8+ 僅靜態) |
| 構造函數 | 支持 (protected 供派生類調用) | 不支持 |
| 訪問修飾符 | 完整支援 (public/protected/private/internal) | 默認 public,C# 8+ 支援 private/protected/internal (默認實現/靜態) |
| 繼承/實現 | 單繼承 (class A : Base) | 多實現 (class A : IFoo, IBar) |
| 虛方法預設 | abstract 方法隱式 virtual;實體方法可 virtual | 成員隱式非虛 (C# 8+ 默認實現非虛),需顯式 virtual |
| 密封 | 可 sealed | 不可 |
抽象類 = 「是一種」:定義核心身份、共享狀態與行為骨架。
介面 = 「能做什麼」:定義行為契約、能力標簽,無狀態耦合。
Animal → Dog/Cat、Stream → FileStream/MemoryStream)。IDisposable、IComparable、ISerializable)。| 操作 | 抽象類 | 介面 (C# 8 前) | 介面 (C# 8+ 默認實現) |
|---|---|---|---|
| 新增非抽象成員 | ✅ 安全 (現有派生類不受影響) | ❌ 破壞性變更 (所有實現類必須修改) | ✅ 安全 (提供默認實現) |
| 新增抽象成員 | ❌ 破壞性 (派生類必須實現) | ❌ 破壞性 | ❌ 破壞性 (除非有默認實現) |
結論:預計頻繁擴展成員 → **抽象類**;穩定契約、廣泛分發 → **介面**。
NotImplementedException)。Interface Segregation Principle)。Page.Server 實為 HttpServerUtility 實例)。abstract 方法,延遲到具體子類實現。
需要共享字段/構造函數/實現邏輯? → YES → 抽象類
↓ NO
需要多實現/廣泛分發/穩定契約? → YES → 介面
↓ NO
僅需提供默認行為供可選覆寫? → YES → 介面 + 默認實現 (C# 8+)
↓ NO
考慮具體類 + 組合
「抽象類定義骨架,介面定義契約,組合構建對象。」—— 這是應對變化、控制複雜度的鐵三角。