第五節、實現接口
1、顯式實現接口成員
為了實現接口,類可以定義顯式接口成員執行體(Explicit interface member implementations)。顯式接口成員執行體可以是一個方法、一個屬性、一個事件或者是一個索引指示器的定義,定義與該成員對應的全權名應保持一致。
using System ; interface ICloneable { object Clone( ) ; } interface IComparable { int CompareTo(object other) ; } class ListEntry: ICloneable, IComparable { object ICloneable.Clone( ) {…} int IComparable.CompareTo(object other) {…} }
上面的代碼中ICloneable.Clone 和IComparable.CompareTo 就是顯式接口成員執行體。
說明:
1、不能在方法調用、屬性訪問以及索引指示器訪問中通過全權名訪問顯式接口成員執行體。事實上,顯式接口成員執行體只能通過接口的實例,僅僅引用接口的成員名稱來訪問。
2、顯式接口成員執行體不能使用任何訪問限制符,也不能加上abstract, virtual, override或static 修飾符。
3、顯式接口成員執行體和其他成員有著不同的訪問方式。因為不能在方法調用、屬性訪問以及索引指示器訪問中通過全權名訪問,顯式接口成員執行體在某種意義上是私有的。但它們又可以通過接口的實例訪問,也具有一定的公有性質。
4、只有類在定義時,把接口名寫在了基類列表中,而且類中定義的全權名、類型和返回類型都與顯式接口成員執行體完全一致時,顯式接口成員執行體才是有效的,例如:
class Shape: ICloneable { object ICloneable.Clone( ) {…} int IComparable.CompareTo(object other) {…} }使用顯式接口成員執行體通常有兩個目的:
1、因為顯式接口成員執行體不能通過類的實例進行訪問,這就可以從公有接口中把接口的實現部分單獨分離開。如果一個類只在內部使用該接口,而類的使用者不會直接使用到該接口,這種顯式接口成員執行體就可以起到作用。
2、顯式接口成員執行體避免了接口成員之間因為同名而發生混淆。如果一個類希望對名稱和返回類型相同的接口成員采用不同的實現方式,這就必須要使用到顯式接口成員執行體。如果沒有顯式接口成員執行體,那麼對於名稱和返回類型不同的接口成員,類也無法進行實現。
下面的定義是無效的,因為Shape 定義時基類列表中沒有出現接口IComparable。
class Shape: ICloneable { object ICloneable.Clone( ) {…} } class Ellipse: Shape { object ICloneable.Clone( ) {…} }
在Ellipse 中定義ICloneable.Clone是錯誤的,因為Ellipse即使隱式地實現了接口ICloneable,ICloneable仍然沒有顯式地出現在Ellipse定義的基類列表中。
接口成員的全權名必須對應在接口中定義的成員。如下面的例子中,Paint的顯式接口成員執行體必須寫成IControl.Paint。
using System ; interface IControl { void Paint( ) ; } interface ITextBox: IControl { void SetText(string text) ; } class TextBox: ITextBox { void IControl.Paint( ) {…} void ITextBox.SetText(string text) {…} }
實現接口的類可以顯式實現該接口的成員。當顯式實現某成員時,不能通過類實例訪問該成員,而只能通過該接口的實例訪問該成員。顯式接口實現還允許程序員繼承共享相同成員名的兩個接口,並為每個接口成員提供一個單獨的實現。
下面例子中同時以公制單位和英制單位顯示框的尺寸。Box類繼承 IEnglishDimensions和 IMetricDimensions兩個接口,它們表示不同的度量衡系統。兩個接口有相同的成員名 Length 和 Width。
程序清單1 DemonInterface.cs
interface IEnglishDimensions { float Length ( ) ; float Width ( ) ; } interface IMetricDimensions { float Length ( ) ; float Width ( ) ; } class Box : IEnglishDimensions, IMetricDimensions { float lengthInches ; float widthInches ; public Box(float length, float width) { lengthInches = length ; widthInches = width ; } float IEnglishDimensions.Length( ) { return lengthInches ; } float IEnglishDimensions.Width( ) { return widthInches ; } float IMetricDimensions.Length( ) { return lengthInches * 2.54f ; } float IMetricDimensions.Width( ) { return widthInches * 2.54f ; } public static void Main( ) { //定義一個實類對象 "myBox":: Box myBox = new Box(30.0f, 20.0f); // 定義一個接口" eDimensions":: IEnglishDimensions eDimensions = (IEnglishDimensions) myBox; IMetricDimensions mDimensions = (IMetricDimensions) myBox; // 輸出: System.Console.WriteLine(" Length(in): {0}", eDimensions.Length( )); System.Console.WriteLine(" Width (in): {0}", eDimensions.Width( )); System.Console.WriteLine(" Length(cm): {0}", mDimensions.Length( )); System.Console.WriteLine(" Width (cm): {0}", mDimensions.Width( )); } }