Henry的VB.NET之旅(八)—介面

latitude發表於2003-12-11

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

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

?

“還有兩種繼承方法?”我是真正被VB.NET的強大功能所折服了。求知的渴望驅使著我向大李露出了一個最燦爛的笑容,“行了,別傻笑了,我告訴你不就成了。”大李不禁也笑了起來。

“剛才我說到‘脆弱的基類’時,就提到實現繼承最大的問題,就在於基類與派生類之間的關係過於緊密,還記得吧?基類實現細節往往會洩露出來,這不是我們願意看到的封裝情況,所以有很多程式設計師就想盡方法來改進這一問題,其中最出名的,就是COM了。”

COM?我在VB6中經常用呀,是一種元件形式呀。”我不是太明白大李的話,這和麵向物件的繼承有什麼關係?

“你說的不錯,正是通過元件的這種封裝方式,我們就可以把實現繼承侷限於在元件內部使用,而我們使用元件時,就不用理會它內部是什麼,怎麼實現的。這就可以避免不可預測地對基類的修改。我們把利用元件的組織程式方法稱為面向元件程式設計,但這也是一種物件導向的設計方法,不過是更具強制性。元件支援元件內部的實現繼承,還支援介面繼承。”

“介面繼承,我不是太清楚。不過,介面我是清楚的,就是元件開放的屬性、方法與事件、公用變數的定義方法。我在VB6中也接觸過介面程式設計,不是太方便,好象要把定義了方法卻沒有寫實現過程的類編譯成DLL檔案,VB6會自動將它建立為介面,不過只能是隱藏的,不是顯式定義的。”我回憶了一下說。

大李微微點了點頭說:“從物件導向的觀點來看,介面就是物件的外觀,而物件實際的工作方式就是實現。把介面與實現分離開就是我們要進行封裝的動機。使用者只能通過介面來操作,但是看不到具體的實現的程式碼。”

大李頓了一頓,然後接著說:“VB.NET 以前的 Visual Basic 版本可以使用介面,但不能直接建立它們。VB.NET 卻是允許可以用 Interface 語句定義真正的介面的喔!”

此言一出,真讓我大吃一驚。“我們也可以直接定義介面嗎?”

“當然,”大李說,“在VB.NET中,和類一樣,介面也可以定義屬性、方法和事件。但正如我剛才說到的,與類不同的是,介面並不提供實現。現在的介面,是由類來實現的,並從類中被定義為單獨的實體。”

大李手指在桌面上重重的敲了一下,加強了一下語氣:“我們可以這樣來理解,介面表示的是一種約定。實現介面的類必須嚴格按其定義來實現介面的每個方面。有了介面,就可以將功能定義為一些緊密相關成員的小組。可以在不危害現有程式碼的情況下,開發介面的增強型實現,從而使相容性問題最小化。也可以在任何時候通過開發附加介面和實現來新增新的功能。雖然介面實現可以進化,但介面本身一旦被髮布就不能再更改。對已釋出的介面進行更改會破壞現有的程式碼。若把介面視為約定,很明顯約定雙方都各有其承擔的義務。介面的釋出者同意不再更改該介面,介面的實現者則同意嚴格按設計來實現介面。”

“也就是說,在VB.NET中,介面是用類來實現的,就象是個抽象類,只是關鍵字用的是Interface,不是class,對嗎?”我還是很好奇。

“介面的實現可以是類,也可以是結構。介面的定義用的是Interface關鍵字,實現時用的是Implements關鍵字”大李淡淡的一句話,使我在心中開始回憶起類和結構的差別來(詳見前文《類和結構》)。

大李接著跟我解說:“介面的成員包括其成員宣告引入的成員和從其基介面繼承的成員。只有巢狀型別、方法、屬性和事件才能作為介面成員。方法和屬性不能有實體。介面成員隱式地定為是Public,而且不能指定訪問修飾符。介面自已倒是可以新增修飾符。”大李跟著看了我一眼,就在電腦上開始寫起示例來:

Public Interface IHenry

??? Sub subX(ByVal x As Integer)

??? Function fcnY(ByVal y As Integer) As Long

??? Property proZ() As String

End Interface

Public Class CHenry

??? Implements IHenry

??? Private z1 As String

??? Sub subX(ByVal x As Integer) Implements IHenry.subX

??????? '填寫實現程式碼

??? End Sub

??? Function fcnY(ByVal y As Integer) As Long Implements IHenry.fcnY

??????? '填寫實現程式碼

??? End Function

??? Property proZ() As String Implements IHenry.proZ

??????? Get

??????????? Return z1

??????? End Get

??????? Set(ByVal Value As String)

??????????? z1 = Value

??????? End Set

??? End Property

End Class

?

?

大李指著程式碼說:“你看,我用Interface定義了一個介面IHenry(筆者注:一般來說,介面的命名第一個字母為I,這並沒有什麼強制的含義,但卻是一個通用的命名規則),內含三個方法與屬性的定義,但並沒有實現;實現程式碼寫在CHenry類中。你可以按我剛才說的約定的思路來理解,IHenry介面其實就是一個合約的提綱,CHenry是該合約的一個操作版本,只要在CHenry中實現了介面IHenry定義的所有的方法,不管是怎麼實現的,有沒有加入新的方法,都可認為CHenry是支援IHenry介面的一個實現類。”

“一個實現類?也就是說介面可以有多個實現嘍?”我不解地問。

“當然,我剛才說過,介面其實就是一個物件的外觀,在VB.NET中有很多很重要的介面,定義了很多種型別的物件,比如說你所熟悉的Windows Form的控制元件,它們的基類大部分是Component類,而Component類就是IComponent介面的一個實現類,IComponent類還有其它三個實現類,那就是:Control、HttpApplication和MarshalByValueComponent類,分別完成不同的功能,但它們都要實現IComponent介面所定義的方法與屬性,且引數定義與返回型別都要與介面定義時的簽名一致。換個角度來看這個問題,我們如何建立一個元件,且讓系統都識別,靠的就是對介面的實現。要成為元件的類必須實現 IComponent 介面,並提供不需要引數或只需一個型別為 IContainer 的引數的基本建構函式就行了。”

“哦,我明白了,通過介面,我們可以定義下某種物件的基本外觀,然後可以自由地進行實現與擴充套件,卻不涉及對原型的直接修改。太棒了!”我一下子高興了起來。

“是呀,在VB.NET中可以顯式定義介面,使得介面程式設計也成為很棒的程式設計方式了。剛才所說的,在不同的類中實現同一個介面,不就是一種用介面實現的多型性嗎?另外,在類和結構中也可以實現多個介面。”大李寫了如下的程式碼給我看:

?

Interface IOne

???? Sub SubOne()

End Interface

Interface ITwo

???? Sub SubTwo()

End Interface

Class CHenry

???? Implements IOne

???? Implements ITwo

???? Sub SubOne() Implements IOne.SubOne

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

???? End Sub

???? Sub SubTwo() Implements ITwo.SubTwo

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

???? End Sub

End Class

?

“真有意思,”我饒有興致地看著程式碼,“也就是說CHenry就具備了IOne與ITwo所定義的外觀特點了。”

我一下子想起了抽象類的定義,不由好奇地說:“如果把介面看成一個基類,那麼用於實現的類不就可以看成是它的一個派生類了?這是不是就是介面繼承呀?”

?

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

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

QQ: 18349592

E-Mail: henry7685@hotmail.com

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

相關文章