任何一個C#入門的程序員都知道——當一個類型在實現接口的時候,有兩種方法實現:顯式實現、隱式實現。並且你們也都知道,當一個類型實現的兩個接口存在相同成員定義時,顯示實現能夠解決這種狀況。html
可是,在一個命名比較規範的項目中,幾乎不可能出現上述狀況。程序員
那麼,顯示實現有什麼具體存在的意義嗎?數據庫
本人根據這小几年的開發歷經,感受顯式實現最覺的兩個做用就是:框架
下面本人將會對這兩種做用進一一說明函數
本篇文章將會使用一個示例來說述這兩個做用。this
咱們先來看一下示例吧:spa
例子仍是挺簡單的,咱們來把這些接口類型碼出來吧:code
/// <summary> /// 一個元件接口 /// </summary> interface IComponent { /// <summary> /// 元件的名稱,用於區別於其它元件 /// </summary> String ComponentName { get; } /// <summary> /// 使用這個元件 /// <param name="target">對哪一個對象使用這個元件</param> /// </summary> void Use(Object target); } /// <summary> /// 一個元件工廠接口 /// </summary> interface IComponentFactory { /// <summary> /// 建立元件 /// </summary> /// <param name="componentName"></param> /// <returns></returns> IComponent CreateComponent(String componentName); /// <summary> /// 註冊一個元件 /// </summary> /// <param name="component"></param> void RegistComponent(IComponent component); }
光有接口,咱們是沒法工做的。所以咱們開發一個叫鑰匙的元件,再開發一個密碼鎖,鑰匙能夠用來開密碼鎖,當二者的編號相同時,鎖才能夠被打開。咱們再作一個工廠,根據鎖的編號生成一把鑰匙,而後就能夠開鎖了。component
咱們先用隱式實現來作這件事htm
/// <summary> /// 密碼鎖 /// </summary> class PasswordLocker { /// <summary> /// 開鎖用的密碼 /// </summary> public String Code { get; set; } } /// <summary> /// 鑰匙 /// </summary> class Key : IComponent { /// <summary> /// 對應的解鎖密碼,只有和鎖的Code相同時才能夠開鎖 /// </summary> public string Code { get; set; } public string ComponentName { get { return this.Code; } } public void Use(object target) { //因爲入參是繼承了接口的Object類型,因此必須先對入參進行類型判斷 if (target is PasswordLocker) { PasswordLocker pl = (PasswordLocker)target; if (pl.Code == this.Code) Console.WriteLine("打開鎖了"); else Console.WriteLine("未能把鎖打開"); } else Console.WriteLine("目前類型不是鎖,暫時不能使用該元件"); } } /// <summary> /// 鑰匙工廠 /// </summary> class KeyFactory : IComponentFactory { private Dictionary<String, IComponent> components = new Dictionary<string, IComponent>(); public IComponent CreateComponent(string componentName) { return components[componentName]; } /// <summary> /// 由外部建立一個元件 /// </summary> /// <param name="component"></param> public void RegistComponent(IComponent component) { components[component.ComponentName] = component; } }
而後咱們再寫一代段碼使用他們:
PasswordLocker locker = new PasswordLocker(); locker.Code = "12345"; Key k = new Key(); k.Code = "12345"; KeyFactory factory = new KeyFactory(); factory.RegistComponent(k); factory.CreateComponent(locker.Code).Use(locker);
功能所有OK,可是有一些小小的瑕疵:
確實如此,當一個項目大到多人合做的時候,可以有着明確的入參與返回類型和私有化不須要其它人員調用的成員,是頗有必要的一件事。
因此如今回頭看剛纔的那段實現代碼,咱們能夠提出如下要求:
咱們經過對接口的顯示實現,以保證接口成員不能夠被顯示的調用。再定義須要的public方法,調用接口成員,以達到上面三個要求:
/// <summary> /// 這是一個僅僅能用於開密碼鎖的元件,使用了現式實現改變入參 /// </summary> class PasswordLockerKey : IComponent { private string code; public PasswordLockerKey(String code) { this.code = code; } string IComponent.ComponentName { get { return this.code; } } void IComponent.Use(object target) { PasswordLocker pl = (PasswordLocker)target; if (pl.Code == this.code) Console.WriteLine("打開鎖了"); else Console.WriteLine("未能把鎖打開"); } /// <summary> /// 利用顯示繼承,隱藏了以Object做爲入參的方法,並開放了一個僅僅以PasswordLocker做爲入參的方法。改變了參數類型 /// </summary> /// <param name="locker"></param> public void User(PasswordLocker locker) { //將自身轉化爲接口類型,再調用Use纔可使用顯式實現的方法 ((IComponent)this).Use(locker); } } /// <summary> /// 基於數據庫的鑰匙工廠,使用顯式實現改變了接口成員的訪問權限 /// </summary> class DataBaseKeyFactory : IComponentFactory { private Dictionary<String, PasswordLockerKey> keys = new Dictionary<string, PasswordLockerKey>(); /// <summary> /// 在構造函數的同時,從數據庫中加載出全部鑰匙 /// </summary> public DataBaseKeyFactory() { IComponentFactory f = (IComponentFactory)this; foreach (PasswordLockerKey k in LoadKeyFromDatabase()) { f.RegistComponent(k); } } /// <summary> /// 這是模擬的經過數據庫加載鑰匙的方法 /// </summary> /// <returns></returns> protected virtual IEnumerable<PasswordLockerKey> LoadKeyFromDatabase() { return new List<PasswordLockerKey>() { new PasswordLockerKey("12345") }; } IComponent IComponentFactory.CreateComponent(string componentName) { return keys[componentName]; } void IComponentFactory.RegistComponent(IComponent component) { keys[component.ComponentName] = (PasswordLockerKey)component; } /// <summary> /// 這裏改變了本來接口的返回類型 /// </summary> /// <param name="code"></param> /// <returns></returns> public PasswordLockerKey CreateComponent(string code) { return (PasswordLockerKey)((IComponentFactory)this).CreateComponent(code); } }
代碼中模擬了一下從數據庫中取數的過程。
經過上面的方法,咱們最終在使用這些類形的時候會發現,Use的入參對象只能是PasswordLocker,Factory不能夠Regist成員了,Create時必定是PasswordLockerKey類型。已經基本知足上面的須要了。
在實際項目中,其實這些現象依然是不多見的。每每出如今底層接口框架被搭建好後,對接口類型進行一次基礎實現時,可能會遇到這些問題。
本人寫此文章,但願你們在遇到相似問題的時候,可以想到可使用接口的顯示實現來解決。
但願可以你們帶來一些提示和幫助。
文章爲做者原創,轉載請註明出處http://www.cnblogs.com/ShimizuShiori/p/5468749.html ,謝謝