Henry的VB.NET之旅(九)—介面繼承

latitude發表於2003-12-11

?????? Henry的VB.NET之旅(九)—介面繼承<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

?????????????????????????????????????? 韓睿?

大李拍了拍我的肩膀說:“你真有想象力,不過的確,有很多文獻把這種用Implements來實現介面的方法就稱為介面繼承。其實,介面自己也是可以進行繼承的,在VB.NET中把介面間的繼承形式稱為介面繼承。”

我不禁跟著笑了起來:“介面繼承要成為繼承,當然要用Inherits,對吧?”

大李點點頭說:“既然你都清楚了,那你來模擬一個下拉框Combobox的介面吧。”

Combobox?”我不禁一愣,不過一會就想明白了,“是不是要讓它符合有文字框供文字輸入與下拉選單供選擇列表項的組合形式這樣的外觀?”

大李跟著提醒了我一句:“介面與VB.NET中的類繼承還是有不同的,它可以支援從多個介面進行多重繼承,VB.NET中的類只支援單一基類的繼承。”

見大李沒什麼別的意見,我就開始寫起程式碼來:

?

Interface IControl

???? Sub Paint()

End Interface

Interface ITextBox

Inherits IControl

在文字框設定文字

??? ?Sub SetText(ByVal text As String)

End Interface

Interface IListBox

Inherits IControl

在下拉選單設定列表項

???? Sub SetItems(ByVal items() As String)

End Interface

Interface IComboBox

??? Inherits ITextBox, IListBox

End Interface

Class CHenry

??? Implements IComboBox

???? Sub SetText(ByVal text As String) Implements ITextBox.SetText

??????? '實現程式碼

???? End Sub

???? Sub SetItems(ByVal items() As String) Implements IListBox.SetItems

??????? '實現程式碼

???? End Sub

……

?

寫到這,發現CHenry類中的Implements IcomboBox的ICombobox下面還有一條波浪線,說明介面並沒有實現完畢,可是我已經把IComboBox繼承的兩個基介面中的方法都已經實現了呀。把滑鼠靠近波浪線一看,系統提示“必須為介面IControl實現sub Paint()”,於是我就繼續寫:

Sub Paint() Implements IControl.Paint

??????????? '實現程式碼

??? End Sub

End Class

?

?

我轉回頭問大李:“介面的實現類中是不是要把介面的所有基介面都要實現一遍呀?”

大李點點頭說:“如果象這個演練中的情況,當然是要把基介面中沒有實現的方法進行實現。但也要注意,實現介面的類或結構會隱式地實現該介面的所有基介面。如果一個介面在基介面的可傳遞閉包中多次出現,它的成員只參與一次構成派生介面。實現派生介面的型別只需實現一次多次定義的基介面方法。所以你也可以用Sub Paint() Implements ITextbox.Paint或是Sub Paint() Implements IListBox.Paint來代替,但只能用這三個定義中的一個。你再來看這段程式碼。”大李開始修改起剛寫好的程式碼來:

?

Interface IControl

???? Sub Paint()

End Interface

Interface ITextBox

Inherits IControl

在文字框設定文字

Sub SetText(ByVal text As String)

Shadows Sub Paint()

End Interface

Interface IListBox

Inherits IControl

在下拉選單設定列表項

???? Sub SetItems(ByVal items() As String)

End Interface

Interface IComboBox

??? Inherits ITextBox, IListBox

End Interface

Sub test(ByVal x As IComboBox)

??? x.Paint()

End Sub

?

“這裡的x.Paint()是哪一個介面的方法?IControlITextBox?”大李一臉笑意,真是氣人。但是,我應該可以回答上來的,我按類的隱藏的概念回憶了一下(詳見前文《過載和隱藏》),哈,明白了,它當然是呼叫它直接被派生的那個基類中的方法呀。

“是ITextBox中的方法吧!”

“可以呀,不錯!”大李簡單地誇了我一句,然後喝了口水,繼續說:“基介面的成員名稱在繼承分層結構的一條路徑中被隱藏,但它在其它的路徑中不會被隱藏,比如我們可以從IlistBox中去繼承Icontrol中的Sub Paint()。”

“可是,在您的這個示例中的sub test裡,x是介面的例項嗎?可是,介面還沒有實現呀?”我還是有問題要問。

test方法其實可以接受任何將 IComboBox 實現為小部件引數的物件,即使對介面 IComboBox 的實現可能相差很大。”大李回答道。

“是不是說我們在使用的時候,可以用實現IComboBox介面的類,比如CHenry的一個例項去代替x?”

大李笑著說:“基本上差不多了,你自己慢慢考慮吧。還有個問題比較有意思:實現類中用於實現介面的方法或屬性名倒不用與介面中定義的名字一樣,只要引數列表與返回型別一致就行了。比如在CHenry中的sub Paint()如果更名為sub xxx()也是可以的,只要後面跟著Implements IControl.Paint就行了。命名一定要有規劃,不然,介面繼承中也會帶來命名重複造成的問題,我們來看一下。”

?

Interface IHenry1

???? Property yyy() As Integer

End Interface

Interface IHenry2

??? Sub yyy(ByVal i As Integer)

End Interface

Interface IHenryDerived

??? Inherits IHenry1

??? Inherits IHenry2

End Interface

Sub test(ByVal x As IHenryDerived)

??? x.yyy(1)

??? x.yyy = 10

End Sub

?

“你看,在sub test()中,無論你按IHenry2中的定義方式來使用x.yyy(1),還是用IHenry1中的方式來使用x.yyy=10,整合編譯器都會在它們下方打上波浪線,表示出錯,是什麼錯呢?”大李一邊問我,一邊把滑鼠靠近波浪線,出現了編譯器的出錯提示:

yyy”在繼承介面“IHenry1”與“IHenry2”之間不明確

“所以,我一直強調命名規則,對吧?”大李看了我一眼,“其實解決方法倒用不著去更改基介面中的方法與屬性名。”

Sub test()

??? Dim x As IHenryDerived

??? CType(x, IHenry1).yyy = 10

??? CType(x, IHenry2).yyy(1)

End Sub

?

“哦,用強制型別轉換就可以了。”我又學到一招,不禁暗自竊喜。但是我心裡總是有一個不大不小的疙瘩,說來說去,這介面與抽象類可真的太象了。趕緊得問問:“大李哥,這介面與……”

“抽象類?”大李一口就接了上來:“別急,小夥子,看看幾點了,該下樓吃午飯了。”

?

---------------------------------------------------------------

宣告:本文版權與解釋權歸韓睿所有,如需轉載,請保留完整的內容及此宣告。

QQ: 18349592

E-Mail: henry7685@hotmail.com

請訪問本人專欄:http://www.csdn.net/develop/author/netauthor/Latitude/

相關文章