在物件導向設計中,介面是定義「能做什麼」的契約,而類別負責實作「怎麼做」。介面只宣告成員(方法、屬性、事件、索引子)的簽章,不包含實作細節。這種關注點分離讓系統具備高內聚、低耦合的特性,是依賴倒置原則與多型的核心基石。
使用 interface 關鍵字定義介面,慣例以 I 開頭命名(如 IComparable、IDisposable):
public interface ITransaction {
void ShowTransaction(); // 方法簽章
decimal GetAmount(); // 傳回值型別
string ReferenceCode { get; } // 唯讀屬性
event EventHandler Processed; // 事件
}
介面成員預設為 public,不允許標示存取修飾詞(C# 8.0 前)。
類別直接定義與介面簽章相符的 public 成員:
public class Transaction : ITransaction {
public string ReferenceCode { get; private set; }
public decimal Amount { get; private set; }
public event EventHandler Processed;
public Transaction(string code, decimal amount) {
ReferenceCode = code;
Amount = amount;
}
public void ShowTransaction() {
Console.WriteLine($"交易:{ReferenceCode},金額:{Amount:C}");
}
public decimal GetAmount() => Amount;
}
當類別實作多個介面且成員簽章衝突,或需隱藏實作細節時,使用顯式介面實作:
public class MultiFormatExporter : IJsonExporter, IXmlExporter {
// 顯式實作:只能透過介面型別存取
void IJsonExporter.Export(data) { /* JSON 邏輯 */ }
void IXmlExporter.Export(data) { /* XML 邏輯 */ }
// 隱含實作:可直接透過類別實例存取
public void ExportDefault(data) { /* 預設邏輯 */ }
}
顯式實作的成員不可標示 public,且只能透過介面型別變數呼叫:
var exporter = new MultiFormatExporter();
((IJsonExporter)exporter).Export(data); // 必須轉型
exporter.ExportDefault(data); // 直接呼叫
| 特性 | 介面 | 抽象類別 |
|---|---|---|
| 多重實作 | 類別可實作多個介面 | 只能繼承單一抽象類別 |
| 預設實作 | C# 8.0+ 支援 default 實作 | 可包含完整實作與狀態 |
| 建構子 | 無 | 可有建構子 |
| 存取修飾詞 | 成員預設 public | 支援完整存取控制 |
| 適用場景 | 定義能力契約、跨層級解耦 | 共享程式碼、定義核心實體骨架 |
經驗法則:優先使用介面定義契約;當需要共享邏輯或狀態時,才考慮抽象類別。
介面可提供成員的預設實作,實作類別可選擇覆寫:
public interface ILogger {
void Log(string message);
void LogError(string message) => Log($"[ERROR] {message}"); // 預設實作
}
介面現在支援 static 成員、private 輔助方法,方便預設實作共用邏輯:
public interface ICalculator {
static int Add(int a, int b) => a + b; // 靜態方法
int Calculate(int x); // 實作類別必須實作
}
介面是策略模式的核心——定義演算法族群的共同契約:
// 策略介面
public interface IDiscountStrategy {
decimal CalculateDiscount(decimal originalPrice);
}
// 具體策略
public class VipDiscount : IDiscountStrategy {
public decimal CalculateDiscount(decimal price) => price * 0.85m;
}
public class SeasonalDiscount : IDiscountStrategy {
public decimal CalculateDiscount(decimal price) => price * 0.9m;
}
// 內容類別
public class Order {
private readonly IDiscountStrategy _strategy;
public Order(IDiscountStrategy strategy) => _strategy = strategy;
public decimal GetFinalPrice(decimal price) => _strategy.CalculateDiscount(price);
}
// 使用
var order = new Order(new VipDiscount());
Console.WriteLine(order.GetFinalPrice(1000)); // 850
I 開頭 + 形容詞/名詞(ISortable、IRepository)。A: 可以。interface IExtended : IBase { } 形成介面繼承鏈,實作類別必須實作所有成員。
A: 可以。結構支援介面實作,但不可繼承類別。這是實現值型別多型的重要方式。
A: 1) 解決多介面同名成員衝突 2) 隱藏實作細節,強制透過介面存取 3) 實作介面成員但不想汙染類別的公用 API。