| 特性 | 介面 | 抽象類別 |
|---|---|---|
| 關鍵字 | interface | abstract class |
| 成員類型 | 方法、屬性、事件、索引子 (皆隱含 public abstract) | 任意成員 (欄位、建構函式、非抽象方法、私有成員等) |
| 實作 | 不可包含實作 (C# 8.0 前) / 可含預設實作 (C# 8.0+) | 可包含完整實作與共享邏輯 |
| 繼承限制 | 類別可實作多個介面 | 類別單一繼承 |
| 建構函式 | 無 | 可有 (供衍生類別呼叫) |
| 存取修飾詞 | 成員預設 public,不可為 private/protected (C# 8.0 前) | 支援完整存取修飾詞 |
| 版本演進 | 修改介面 = 破壞所有實作類別 (C# 8.0 前) | 新增非抽象成員 = 不破壞衍生類別 |
// 契約定義
public interface IAnimal {
int EyeCount { get; }
void MakeSound(); // 強制實作,命名統一
}
// 實作
public class Dog : IAnimal {
public int EyeCount => 2;
public void MakeSound() => Console.WriteLine("Woof!");
}
public class Cat : IAnimal {
public int EyeCount => 2;
public void MakeSound() => Console.WriteLine("Meow~");
}
// 多型使用:介面型別參數
public void Feed(IAnimal animal) {
Console.WriteLine($"Feeding {animal.GetType().Name}");
animal.MakeSound(); // 動態派發,Dog/Cat 行為不同
}
// 新增類別零修改既有代碼
public class Duck : IAnimal { ... } // 直接串接
Bark()/Woof()/MakeNoise() 混亂。public abstract class AnimalBase {
// 共享欄位/邏輯
protected int _legs = 4;
public int Legs => _legs;
// 共享實作 (封裝)
public void Sleep() => Console.WriteLine("Zzz...");
// 模板方法模式
public void DailyRoutine() {
WakeUp();
Eat(); // 抽象,強制子類實作
Play();
Sleep();
}
protected abstract void Eat();
protected virtual void WakeUp() => Console.WriteLine("Wake up");
protected virtual void Play() => Console.WriteLine("Playing");
}
public class Dog : AnimalBase {
protected override void Eat() => Console.WriteLine("Eating bone");
}
DailyRoutine() 定義演算法骨架,子類只填細節。virtual 方法不破壞既有衍生類別;介面新增成員 (無預設實作) 則強制所有實作類別修改。IDisposable, IComparable, ISerializable)。interface 預設實作。// 1. 介面定義契約
public interface IRepository {
T GetById(int id);
void Save(T entity);
}
// 2. 抽象類別提供共享基礎設施 (連線管理、日誌、事務)
public abstract class RepositoryBase : IRepository {
protected readonly IDbConnection _conn;
protected RepositoryBase(IDbConnection conn) => _conn = conn;
public abstract T GetById(int id);
public abstract void Save(T entity);
protected void Log(string msg) => /* 共享日誌 */;
}
// 3. 具體實作
public class SqlUserRepository : RepositoryBase {
public SqlUserRepository(IDbConnection conn) : base(conn) {}
public override User GetById(int id) => /* SQL 查詢 */;
public override void Save(User u) => /* SQL 存儲 */;
}
介面 = 契約 + 多型 + 解耦 + 多重實作。抽象類別 = 代碼復用 + 封裝 + 模板方法 + 版本穩定。現代 C# 開發常見模式:介面定義 API 邊界,抽象類別提供骨幹實作,具體類別繼承抽象類別並實作介面。單一繼承限制下,善用介面組合能力,抽象類別共享邏輯,是優雅物件導向設計的關鍵。