介面與抽象類是物件導向設計中「面向抽象編程」的兩大支柱。雖然兩者都無法直接實例化、都定義契約供衍生類實作,但其適用場景、能力邊界與設計意圖截然不同。本文將從概念、異同、14 條實戰法則、經典範例與社群觀點五個維度,幫你建立清晰的決策框架。
| 特性 | 介面 | 抽象類別 |
|---|---|---|
| 繼承模式 | 多重實作 (: 介面1, 介面2) | 單一繼承 (: 基類) |
| 成員類型 | 僅簽名:方法、屬性、索引子、事件 | 可含欄位、已實作方法、建構函式、抽象成員 |
| 存取修飾詞 | 預設 public,不可標記 | 可使用 public/protected/internal/private |
| 靜態成員 | C# 不允許(CLR 允許) | 允許 |
| 適用類型 | 值類型 (struct) 與引用類型皆可 | 僅限引用類型 |
| 設計意圖 | CAN-DO 行為契約(如 IComparable) | IS-A 型別階層,共享實作與狀態 |
| 版本演進 | 新增成員會破壞所有實作類別 | 可在基類新增實作,不強制衍生類修改 |
| 回呼支援 | 支援(介面型別參數) | 不支援(單一繼承限制) |
Animal → Dog/Cat)IDisposable、IComparable)IEnumerable、IEquatable 等皆僅一核心方法IInterface2),勿修改既有介面I 前綴(如 IRepository)sealed/new:因不可實例化static/virtual:語意衝突System.Collections),資料流用抽象類 (System.IO.Stream)// 抽象類:共享狀態與部分實作
public abstract class Animal {
protected string _name;
public abstract string Name { get; }
public abstract void Show();
public void MakeVoice() => Console.WriteLine("All animals can make voice!");
}
// 介面:定義行為契約
public interface IAction { void Move(); }
// 實作雙重契約
public class Duck : Animal, IAction { ... }
public class Dog : Animal, IAction { ... }
// 客戶端:面向抽象程式設計
Animal duck = new Duck("Duck");
duck.MakeVoice(); duck.Show();
IAction dogAction = new Dog("Big Dog");
dogAction.Move();
介面與抽象類無優劣之分,只有適用與否。掌握 T14 法則、閱讀 FCL 設計、大量實作練習,才能在架構決策中游刃有餘。記住:面向抽象編程,才是設計模式落地的靈魂。