給定基類 A 實作介面 IC,衍生類別 B 有兩種宣告方式:
interface IC { void M(); }
class A : IC { void IC.M() { Console.WriteLine("In A"); } }
// 方式一:隱含繼承介面
class B1 : A { }
// 方式二:顯式再次宣告介面
class B2 : A, IC { }
表面上行為相同,但多型行為卻大不同!
class B1 : A { } // 無法重新實作 IC.M
class B2 : A, IC
{
public void IC.M() { Console.WriteLine("In B2"); } // 允許重新實作!
}
static void Main()
{
var list = new List { new A(), new B1(), new B2() };
foreach (var c in list) c.M();
}
/*
輸出:
In A
In A <- B1 被迫繼承 A 的實作
In B2 <- B2 成功覆寫
*/
| 特性 | B1 : A | B2 : A, IC |
|---|---|---|
| 是否可重新實作介面成員 | ❌ 編譯錯誤:'B1.IC.M()': containing type does implement interface 'IC' | ✅ 允許 public void IC.M() 顯式實作 |
| 多型行為 | 鎖死基類實作 | 可自行決定實作 |
| IL 層面 | 介面對應表指向 A 的實作 | 介面對應表指向 B2 的新實作 |
若無法修改基類 A (如來自第三方組件),引入中介類別 AX:
class AX : A, IC
{
// 使用 new 切斷與 A.M 的關聯,virtual 供後代覆寫
public new virtual void M()
{
Console.WriteLine("In AX");
}
// 介面顯式實作轉呼叫虛擬方法
void IC.M() => this.M();
}
class B1 : AX { public override void M() => Console.WriteLine("In B1"); }
class B2 : AX { public override void M() => Console.WriteLine("In B2"); }
B1 不宣告 IC,CLR 繼承 A 的對應表,IC.M 指向 A.IC.M。B2 顯式宣告 IC,CLR 建立新對應表,允許 B2 提供新槽位方法 (顯式實作 void IC.M())。protected virtual 方法,讓衍生類別自然覆寫,避免顯式實作鎖死。class Derived : Base, IInterface 並提供顯式實作,或引入中介類別隔離。class B : A 即可,減少認知負擔。
interface IC1 { }
interface IC2 : IC1 { }
class A1 : IC1 { }
class A2 : IC1, IC2 { } // A1、A2 行為相同 (介面繼承自動包含)
class B1 : A1 { }
class B2 : A1, IC1 { } // B1、B2 行為不同!同樣觸發重新對應機制