5. 是的,我說謊了。[New]
或許你已經注意到,在上面的整個過程中,我做了一個最大的假設,那就是我可以任我喜歡修改A的源代碼!也因為這樣,我可以輕松的糾正這些非預期的多態行為。但實際的情況是,我們不會每次都那麼幸運。如果我們僅僅得到一個包含類A和接口IC的程序集呢?那麼,我們就需要使用到接口的重新映射了。實際上,B2就是使用這種技巧。還是讓我們來看看具體的情況:
接口IC的規格不變。
我們只知道類A的聲明以及它的成員列表和對應的輸出:
Class class A : IC Output
Method public void M(); In class A
Method void IC.M(); In class A
現在我需要實現一批繼承於A的派生類,但我不希望同時繼承A的對應方法的實現,我該怎麼做?很簡單,首先創建一個類AX繼承自類A和接口IC,並在AX裡面處理好相關的事宜,接著讓那批派生類繼承於AX:
class AX : A, IC
{
// 這裡使用new是聲明其與基類的同名方法M沒有任何瓜葛。
// 使用virtual是為後代的繼承打下鋪墊。
public new virtual void M()
{
Console.WriteLine("In class AX");
}
void IC.M()
{
this.M();
}
}
class B1 : AX
{
public override void M()
{
Console.WriteLine("In class B1");
}
}
class B2 : AX
{
public override void M()
{
Console.WriteLine("In class B2");
}
}
好吧,然我們來看看測試程序:
class Program
{
static void Main(string[] args)
{
List<IC> cs = new List<IC>();
cs.Add(new A());
cs.Add(new AX());
cs.Add(new B1());
cs.Add(new B2());
foreach (IC c in cs)
c.M();
Console.WriteLine();
List<AX> ace = new List<AX>();
ace.Add(new AX());
ace.Add(new B1());
ace.Add(new B2());
foreach (AX a in ace)
a.M();
Console.ReadLine();
}
}
我想你已經猜到運行結果了:
In class A
In class AX
In class B1
In class B2
In class AX
In class B1
In class B2
好吧,你辛苦了,如果還沒有頭暈的話,請再聽我說一句。接口重新映射究竟是一個問題還是一種技巧,那要看你實際遭遇的情況。如果你能夠靈活運用的話,它的確會為你帶來巨大的便利!