從技術上講,介面是一組包含了函數型方法的資料結構。通過這組資料結構,客戶代碼可以調用組件對象的功能。
定義介面的一般形式為:
[attributes] [modifiers] interface identifier [:base-list] {interface-body}[;] |
說明:
· attributes(可選):附加的定義性資訊。
· modifiers(可選):允許使用的修飾符有new和四個存取修飾詞。分別是:new、public、protected、internal、private。在一個介面定義中同一修飾符不允許出現多次,new修飾符只能出現在嵌套介面中,表示覆蓋了繼承而來的同名成員。The public, protected, internal, and private修飾符定義了對介面的存取權限。
· 指標和事件。
· identifier:介面名稱。
· base-list(可選):包含一個或多個顯式基底介面的列表,介面間由逗號分隔。
· interface-body:對介面成員的定義。
· 介面可以是命名空間或類的成員,並且可以包含下列成員的簽名: 方法、屬性、索引器 。
· 一個介面可從一個或多個基底介面繼承。
介面這個概念在C#和Java中非常相似。介面的關鍵詞是interface,一個介面可以擴充一個或者多個其他介面。按照慣例,介面的名字以大寫字母"I"開頭。下面的代碼是C#介面的一個例子,它與Java中的介面完全一樣:
interface IShape { void Draw ( ) ;} |
如果你從兩個或者兩個以上的介面派生,父介面的名字列表用逗號分隔,如下面的代碼所示:
interface INewInterface: IParent1, IParent2 { } |
然而,與Java不同,C#中的介面不能包含域(Field)。另外還要注意,在C#中,介面內的所有方法預設都是公用方法。在Java中,方法定義可以帶有public修飾符(即使這並非必要),但在C#中,顯式為介面的方法指定public修飾符是非法的。例如,下面的C#介面將產生一個編譯錯誤。
interface IShape { public void Draw( ) ; } |
下面的例子定義了一個名為IControl 的介面,介面中包含一個成員方法Paint:
interface IControl {void Paint( ) ;} |
在下例中,介面 IInterface從兩個基底介面 IBase1 和 IBase2 繼承:
interface IInterface: IBase1, IBase2 { void Method1( ) ; void Method2( ) ;} |
介面可由類實現。實現的介面的標識符出現在類的基列表中。例如:
class Class1: Iface1, Iface2 { // class 成員。} |
類的基列表同時包含基類和介面時,列表中首先出現的是基類。例如:
class ClassA: BaseClass, Iface1, Iface2 { // class成員。} |
以下的程式碼片段定義介面IFace,它只有一個方法:
interface IFace { void ShowMyFace( ) ;} |
不能從這個定義執行個體化一個對象,但可以從它派生一個類。因此,該類必須實現ShowMyFace抽象方法:
class CFace:IFace{ public void ShowMyFace( ) { Console.WriteLine(" implementation " ) ; } } |
基底介面
一個介面可以從零或多個介面繼承,那些被稱為這個介面的顯式基底介面。當一個介面有比零多的顯式基底介面時,那麼在介面的定義中的形式為,介面標識符後面跟著由一個冒號":"和一個用逗號","分開的基底介面標識符列表。
介面基:
介面類型列表說明:
· 一個介面的顯式基底介面必須至少同介面本身一樣可訪問。例如,在一個公用介面的基底介面中指定一個私人或內部的介面是錯誤的。
· 一個介面直接或間接地從它自己繼承是錯誤的。
· 介面的基底介面都是顯式基底介面,並且是它們的基底介面。換句話說,基底介面的集合完全由顯式基底介面和它們的顯式基底介面等等組成。在下面的例子中
interface IControl {void Paint( ) ;}interface ITextBox: IControl {void SetText(string text) ;}interface IListBox: IControl {void SetItems(string[] items) ;}interface IComboBox: ITextBox, IListBox { } |
IComboBox 的基底介面是IControl, ITextBox, 和 IlistBox。
· 一個介面繼承它的基底介面的所有成員。換句話說,上面的介面IComboBox就像Paint一樣繼承成員SetText 和 SetItems。
· 一個實現了介面的類或結構也隱含地實現了所有介面的基底介面。
介面主體
一個介面的介面主體定義介面的成員。
interface-body:{ interface-member-declarationsopt } |
定義介面成員
介面可以包含一個和多個成員,這些成員可以是方法、屬性、索引指標和事件,但不能是常量、域、操作符、建構函式或解構函式,而且不能包含任何靜態成員。介面定義建立新的定義空間,並且介面定義直接包含的介面成員定義將新成員引入該定義空間。
說明:
· 介面的成員是從基底介面繼承的成員和由介面本身定義的成員。
· 介面定義可以定義零個或多個成員。介面的成員必須是方法、屬性、事件或索引器。介面不能包含常數、欄位、運算子、執行個體建構函式、解構函式或類型,也不能包含任何種類的靜態成員。
· 定義一個介面,該介面對於每種可能種類的成員都包含一個:方法、屬性、事件和索引器。
· 介面成員預設訪問方式是public。介面成員定義不能包含任何修飾符,比如成員定義前不能加abstract,public,protected,internal,private,virtual,override 或static 修飾符。
· 介面的成員之間不能相互同名。繼承而來的成員不用再定義,但介面可以定義與繼承而來的成員同名的成員,這時我們說介面成員覆蓋了繼承而來的成員,這不會導致錯誤,但編譯器會給出一個警告。關閉警告提示的方式是在成員定義前加上一個new關鍵字。但如果沒有覆蓋父介面中的成員,使用new關鍵字會導致編譯器發出警告。
· 方法的名稱必須與同一介面中定義的所有屬性和事件的名稱不同。此外,方法的簽名必須與同一介面中定義的所有其他方法的簽名不同。
· 屬性或事件的名稱必須與同一介面中定義的所有其他成員的名稱不同。
· 一個索引器的簽名必須區別於在同一介面中定義的其他所有索引器的簽名。
· 介面方法聲明中的屬性(attributes), 傳回型別(return-type), 標識符(identifier)和形式參數列表(formal-parameter-lis)與一個類的方法聲明中的那些有相同的意義。一個介面方法聲明不允許指定一個方法主體,而聲明通常用一個分號結束。
· 介面屬性聲明的訪問符與類屬性聲明的訪問符相對應,除了訪問符主體通常必須用分號。因此,無論屬性是讀寫、唯讀或唯寫,訪問符都完全確定。
· 介面索引聲明中的屬性(attributes),類型(type)和形式參數列表(formal-parameter-list)與類的索引聲明的那些有相同的意義。
下面例子中介面IMyTest包含了索引指標、事件E、方法F、屬性P這些成員:
interface IMyTest{ string this[int index] { get; set; } event EventHandler E ; void F(int value) ; string P { get; set; }}public delegate void EventHandler(object sender, EventArgs e) ; |
下面例子中介面IStringList包含每個可能類型成員的介面:一個方法,一個屬性,一個事件和一個索引。
public delegate void StringListEvent(IStringList sender);public interface IStringList{void Add(string s);int Count { get; }event StringListEvent Changed;string this[int index] { get; set; }} |
介面成員的全權名
使用介面成員也可採用全權名(fully qualified name)。介面的全權名稱是這樣構成的。介面名加小圓點"." 再跟成員名比如對於下面兩個介面:
interface IControl { void Paint( ) ;}interface ITextBox: IControl { void GetText(string text) ;} |
其中Paint 的全權名是IControl.Paint,GetText的全權名是ITextBox. GetText。當然,全權名中的成員名稱必須是在介面中已經定義過的,比如使用ITextBox.Paint.就是不合理的。
如果介面是名字空間的成員,全權名還必須包含名字空間的名稱。
namespace System{ public interface IDataTable { object Clone( ) ; }} |
那麼Clone方法的全權名是System. IDataTable.Clone。