第一眼看來,實作介面和覆寫虛方法似乎沒有什麼差別,實際上,實作介面和覆寫虛方法之間的差別很大! ! !
介面中宣告的成員方法預設並非虛方法,所以,衍生類別不能覆寫基底類別中實作介面的非虛成員。
看一個例子。
定義介面ITest:
public interface ITest { void Test(); }
實作介面的Base類別和Derive類別
public class Base:ITest { public Base() { Console.WriteLine("This is base constructor"); } //实现ITest接口 public void Test() { Console.WriteLine("This is in base to ITest implement"); } } public class Derive :Base,ITest { public Derive() { Console.WriteLine("This is derived constructor"); } //测试Derive类实现了ITest吗?? public void Test() { Console.WriteLine("This is in Derive to ITest implement"); } }
呼叫物件Base和Derive:
Base b = new Base(); b.Test(); Base d = new Derive();//将d声明为Base对象 d.Test(); Console.ReadLine();
輸出結果為:
可以看出,b和d實例的Test方法實作的行為都是位於基底類別的! ! !這顯示了,衍生類別不能覆寫基底類別中實作介面的成員(非虛擬方法)
但是,請看下面呼叫:
Base b = new Base(); b.Test(); Derive d = new Derive(); //将d声明为Derive对象 d.Test(); Console.ReadLine();
輸出結果為:
因此,如果想要繼承的物件呼叫介面實作方法,只能宣告為Derive實例。這樣做不符合Effective C#中變數都宣告為基底實例的原則! ! !
避免這種使用上的混淆,如果確實衍生類別實作方法是個性行為,那麼需要將基底類別的實現接口的方法前加virtual修飾符!
程式碼修改如下:
public class Base:ITest { public Base() { Console.WriteLine("This is base constructor"); } public virtual void Test() //实现ITest接口的虚方法 { Console.WriteLine("This is in base to ITest implemnt"); } } public class Derive :Base,ITest { public Derive() { Console.WriteLine("This is derived constructor"); } public override void Test() //实现接口ITest的复写方法 { Console.WriteLine("This is in Derive to ITest implemnt"); } }
觀察上面的程式碼,我們發現,在基類別中實現的接口,如果派生類別也想實現此接口,那麼它預設繼承了基類的接口實現,所以不用重複寫代碼實現接口。
public interface ITest { void Test(); } public class Base:ITest { public Base() { Console.WriteLine("This is base constructor"); } public void Test() { Console.WriteLine("This is in base to ITest implemnt"); } } public class Derive :Base,ITest { public Derive() { Console.WriteLine("This is derived constructor"); } }
總結:
1、 衍生不能覆寫介面的非虛成員;
2、如果衍生類別方法是個性方法,將基底類別方法轉為虛擬方法;
3 、若基類別實作了接口方法,將衍生類別也顯示地繼承此接口,但是不用再實作了! ! !
以上是C#設計模式-衍生類別實作非虛擬介面陷阱的實例程式碼分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!