interface IAnimal {
void Speak();
}
class Dog : IAnimal {
public void Speak() { Console.WriteLine("Woof!"); } // public 必須
}
// 呼叫方式:類別、介面皆可
Dog d = new Dog();
d.Speak(); // OK
IAnimal a = d;
a.Speak(); // OK
interface IAnimal {
void Speak();
}
class Cat : IAnimal {
void IAnimal.Speak() { Console.WriteLine("Meow~"); } // 無 public、無 abstract、介面名稱前綴
}
// 呼叫方式:僅透過介面
Cat c = new Cat();
// c.Speak(); // 編譯錯誤:類別實例不可見
IAnimal a = c;
a.Speak(); // OK
// 強制轉型呼叫
((IAnimal)c).Speak(); // OK
(c as IAnimal)?.Speak(); // OK
| 特性 | 隱式實作 | 顯式實作 |
|---|---|---|
| 存取修飾詞 | 必須 public | 不可寫存取修飾詞 (預設 private) |
| 類別實例可見性 | 可見 | 不可見 |
| 介面參考可見性 | 可見 | 可見 |
| 虛擬/覆寫支援 | 可 virtual/override | 不可 (密封),但可在衍生類重新實作 |
| 多介面同名稱方法衝突 | 無法區分,單一實作服務所有介面 | 可分別實作 IA.Method()、IB.Method() |
| 預設介面方法 (C# 8+) | 可選擇性覆寫 | 不可覆寫預設實作 |
virtual/override)。IList.Add → List.Add)。
interface IPrintable { void Print(); }
interface IScannable { void Print(); } // 同名但語意不同
class MultiFunctionDevice : IPrintable, IScannable {
void IPrintable.Print() => Console.WriteLine("Printing document...");
void IScannable.Print() => Console.WriteLine("Scanning to PDF...");
}
IDisposable.Dispose、IEnumerable.GetEnumerator、IComparable.CompareTo — 避免汙染類別公用 API。現代 C# 開發傾向:**介面方法預設顯式實作**,除非該方法確實屬於類別的公用合約一部分。這能:
interface IBase { void Do(); }
class Base : IBase {
void IBase.Do() { Console.WriteLine("Base"); } // 顯式實作 = 密封
}
class Derived : Base, IBase {
// 無法 override Base 的顯式實作
// 但可「重新實作」介面方法 (隱藏基類實作)
void IBase.Do() { Console.WriteLine("Derived"); } // 新的介面實作
// 或隱式實作 (公開給類別實例)
public void Do() { Console.WriteLine("Derived Public"); }
}
IBase obj = new Derived();
obj.Do(); // 輸出 "Derived" (最衍生類的介面實作優先)
interface ILogger {
void Log(string msg) => Console.WriteLine($"[DEFAULT] {msg}"); // 預設實作
}
class MyLogger : ILogger {
// 顯式實作:無法呼叫 base.Log(),必須完整實作
void ILogger.Log(string msg) => Console.WriteLine($"[CUSTOM] {msg}");
// 隱式實作:可選擇覆寫或繼承預設
// public void Log(string msg) => ... // 若寫這行,類別實例可見
}
ILogger logger = new MyLogger();
logger.Log("Test"); // [CUSTOM] Test
需要實作介面方法
│
├─ 多個介面有同名方法? → 必須顯式實作 (分別實作)
│
├─ 方法為基礎設施介面 (IDisposable, IEnumerable, IComparable...)? → 顯式實作
│
├─ 方法語意屬於類別核心公用 API? → 隱式實作 (public)
│
├─ 需要 virtual/override 多型? → 隱式實作
│
├─ 希望強制消費者用介面參考? → 顯式實作
│
└─ 不確定? → 顯式實作 (較安全、較解耦)