|
第四節(jié)、訪問(wèn)接口 對(duì)接口成員的訪問(wèn) 對(duì)接口方法的調(diào)用和采用索引指示器訪問(wèn)的規(guī)則與類(lèi)中的情況也是相同的。如果底層成員的命名與繼承而來(lái)的高層成員一致,那么底層成員將覆蓋同名的高層成員。但由于接口支持多繼承,在多繼承中,如果兩個(gè)父接口含有同名的成員,這就產(chǎn)生了二義性(這也正是C#中取消了類(lèi)的多繼承機(jī)制的原因之一),這時(shí)需要進(jìn)行顯式的定義:
using System ; 上面的例子中,前兩條語(yǔ)句rs .Count(1)和rs .Count = 1會(huì)產(chǎn)生二義性,從而導(dǎo)致編譯時(shí)錯(cuò)誤,因此必須顯式地給rs 指派父接口類(lèi)型,這種指派在運(yùn)行時(shí)不會(huì)帶來(lái)額外的開(kāi)銷(xiāo)。 再看下面的例子: using System ; 調(diào)用Num.Add(1) 會(huì)導(dǎo)致二義性,因?yàn)楹蜻x的重載方法的參數(shù)類(lèi)型均適用。但是,調(diào)用Num.Add(1.0) 是允許的,因?yàn)?.0 是浮點(diǎn)數(shù)參數(shù)類(lèi)型與方法IInteger.Add()的參數(shù)類(lèi)型不一致,這時(shí)只有IDouble.Add 才是適用的。不過(guò)只要加入了顯式的指派,就決不會(huì)產(chǎn)生二義性。 接口的多重繼承的問(wèn)題也會(huì)帶來(lái)成員訪問(wèn)上的問(wèn)題。例如: interface IBase { 上例中,方法IBase.FWay在派生的接口ILeft中被Ileft的成員方法FWay覆蓋了。所以對(duì)d. FWay (1)的調(diào)用實(shí)際上調(diào)用了。雖然從IBase-> IRight-> IDerived這條繼承路徑上來(lái)看,ILeft.FWay方法是沒(méi)有被覆蓋的。我們只要記住這一點(diǎn):一旦成員被覆蓋以后,所有對(duì)其的訪問(wèn)都被覆蓋以后的成員"攔截"了。 類(lèi)對(duì)接口的實(shí)現(xiàn) 前面我們已經(jīng)說(shuō)過(guò),接口定義不包括方法的實(shí)現(xiàn)部分。接口可以通過(guò)類(lèi)或結(jié)構(gòu)來(lái)實(shí)現(xiàn)。我們主要講述通過(guò)類(lèi)來(lái)實(shí)現(xiàn)接口。用類(lèi)來(lái)實(shí)現(xiàn)接口時(shí),接口的名稱(chēng)必須包含在類(lèi)定義中的基類(lèi)列表中。 下面的例子給出了由類(lèi)來(lái)實(shí)現(xiàn)接口的例子。其中ISequence 為一個(gè)隊(duì)列接口,提供了向隊(duì)列尾部添加對(duì)象的成員方法Add( ),IRing 為一個(gè)循環(huán)表接口,提供了向環(huán)中插入對(duì)象的方法Insert(object obj),方法返回插入的位置。類(lèi)RingSquence 實(shí)現(xiàn)了接口ISequence 和接口IRing。 using System ; 如果類(lèi)實(shí)現(xiàn)了某個(gè)接口,類(lèi)也隱式地繼承了該接口的所有父接口,不管這些父接口有沒(méi)有在類(lèi)定義的基類(lèi)表中列出。看下面的例子: using System ; 這里, 接口IcomboBox繼承了ItextBox和IlistBox。類(lèi)TextBox不僅實(shí)現(xiàn)了接口ITextBox,還實(shí)現(xiàn)了接口ITextBox 的父接口IControl。 前面我們已經(jīng)看到,一個(gè)類(lèi)可以實(shí)現(xiàn)多個(gè)接口。再看下面的例子: interface IDataBound { 類(lèi)EditBox從類(lèi)Control中派生并且實(shí)現(xiàn)了Icontrol和IdataBound。在前面的例子中接口Icontrol中的Paint方法和IdataBound接口中的Bind方法都用類(lèi)EditBox中的公共成員實(shí)現(xiàn)。C#提供一種實(shí)現(xiàn)這些方法的可選擇的途徑,這樣可以使執(zhí)行這些的類(lèi)避免把這些成員設(shè)定為公共的。接口成員可以用有效的名稱(chēng)來(lái)實(shí)現(xiàn)。例如,類(lèi)EditBox可以改作方法Icontrol.Paint和IdataBound.Bind來(lái)來(lái)實(shí)現(xiàn)。 public class EditBox: IControl, IDataBound { 因?yàn)橥ㄟ^(guò)外部指派接口成員實(shí)現(xiàn)了每個(gè)成員,所以用這種方法實(shí)現(xiàn)的成員稱(chēng)為外部接口成員。外部接口成員可以只是通過(guò)接口來(lái)調(diào)用。例如,Paint方法中EditBox的實(shí)現(xiàn)可以只是通過(guò)創(chuàng)建Icontrol接口來(lái)調(diào)用。 class Test { 上例中,類(lèi)EditBox 從Control 類(lèi)繼承并同時(shí)實(shí)現(xiàn)了IControl and IDataBound 接口。EditBox 中的Paint 方法來(lái)自IControl 接口,Bind 方法來(lái)自IDataBound 接口,二者在EditBox 類(lèi)中都作為公有成員實(shí)現(xiàn)。當(dāng)然,在C# 中我們也可以選擇不作為公有成員實(shí)現(xiàn)接口。 如果每個(gè)成員都明顯地指出了被實(shí)現(xiàn)的接口,通過(guò)這種途徑被實(shí)現(xiàn)的接口我們稱(chēng)之為顯式接口成員(explicit interface member)。 用這種方式我們改寫(xiě)上面的例子: public class EditBox: IControl, IDataBound { 顯式接口成員只能通過(guò)接口調(diào)用。例如: class CTest { 上述代碼中對(duì)editbox.Paint( )的調(diào)用是錯(cuò)誤的,因?yàn)閑ditbox 本身并沒(méi)有提供這一方法。control.Paint( )是正確的調(diào)用方式。 注釋?zhuān)航涌诒旧聿惶峁┧x的成員的實(shí)現(xiàn),它僅僅說(shuō)明這些成員,這些成員必須依靠實(shí)現(xiàn)接口的類(lèi)或其它接口的支持。 知道了怎樣訪問(wèn)接口,我們還要知道怎樣實(shí)現(xiàn)接口,要實(shí)現(xiàn)C#的接口,請(qǐng)看下一節(jié)-實(shí)現(xiàn)接口 |
溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!