“類的繼承?”大李點點頭,“以前很多人批評VB的功能不 完善時,都會加上這個條件。但是現在VB.NET中已經是比較完善的面向對象編程 方法了。剛才我們也提到過,類與 VB.NET 的結構類似,讓我們可以定義封裝一 組相關項的數據類型。然而與結構的一個重要區別就是,VB.NET 類可以繼承和擴 展其他類的特性。作為新類的基礎的類稱為‘基類’。從基類派生的 類稱為‘派生類’。派生類繼承基類中定義的所有字段、屬性、方法 和事件。你看,我們只要對類進行一次開發和調試,就可以將其作為其他類的基 礎重復使用。”
“類的繼承的概念我學過的,在VB.NET中是如 何來實際演練呢?”我還是堅持著問。
“我寫段代碼給你看一 下吧,俗話不是說,百聞不如一見嗎?”大李調侃了兩句,噼噼啪啪地開始 敲打起鍵盤來:
Public Class CBaseHenry Private x As Integer = 10 Protected y As Integer Sub New() Console.WriteLine("基類的構造") End Sub Protected Overrides Sub Finalize() Console.WriteLine("基類的析構") MyBase.Finalize() End Sub Public Overridable Function GetY(ByVal x As Integer) As Integer Me.y = me.x + x ‘private類型的me.x只能在基類中使用 Console.WriteLine("基類的GetY方法,結果為:" & Me.y) Return Me.y End Function Public Sub OldY() Console.WriteLine("基類的OldY方法") End Sub End Class
“你看,這是一個基類,我再給你寫個繼承自該類的 派生類。”他一邊說一邊繼續寫:
Public Class CDerivedHenry Inherits CBaseHenry Sub New() MyBase.New() ‘注意:這句話要放在sub內的第一句 Console.WriteLine("派生類的構造") End Sub Protected Overrides Sub Finalize() Console.WriteLine("派生類的析構") MyBase.Finalize() End Sub Public Overrides Function GetY(ByVal x As Integer) As Integer Me.y = x * 10 ‘protected類型的me.y卻可以在派生類中使 用 Console.WriteLine("派生類的GetY方法,結果為:" & Me.y) Return Me.y End Function Public Sub NewY() Console.WriteLine("派生類的新方法") End Sub End Class
“你看清了吧,我們通過聲明Inherits關鍵字,來標 識該類的基類是誰,如果沒有標識的類,比如CBaseHenry,VB.Net就會視其為派 生自Object基類,這是種隱式繼承,和結構是隱式繼承自ValueType 類的方式是 一樣的。”大李指著屏幕跟我解說著。
“那這些overrides與 overload標識是什麼意思呀?”我隱隱感覺到它們的意義,卻沒法清楚地說 出來。
“我們使用繼承,也要允許派生類中的某些屬性或方法有與 基類不同的行為,我們想‘重寫’它,但基類也得要同意你才能重寫 呀,否則不就會發生命名沖突了嗎?因為派生類的對象是可以使用基類的公用成 員的,那怎麼知道哪些基類的方法與屬性是被派生類重寫了呢?所以就必須有一 個約定:我們在基類中用Overridable修飾符來標識允許基類中的屬性或方法在其 派生類中被重寫,沒有標識的其實就是默認為有NotOverridable修飾符來隱式地 標識,用於提醒編譯器該屬性或方法不可被重寫;然後在派生類重寫時,我們就 用Overrides修飾符來標識哪些是重寫自基類中定義的 Overridable 屬性或方法 。”大李娓娓道來,“我們來演練一下對派生類的操作吧。 ”
Public Sub Main() Dim obj As CDerivedHenry = New CDerivedHenry() obj.GetY(4) '調用派生類的GetY方法 obj.OldY() '調用基類的oldY方法 obj.NewY() '調用派生類的NewY方法 End Sub
然後大李按了一下F5鍵,在“輸出”窗口中就出現 了如下的運行結果:
基類的構造 ‘開 始運行New CDerivedHenry() 派生類的構造 派生類的GetY方法,結果為:40 ‘obj.GetY(4)的運行結果=4*10, 不等於基類的(4+10) 基類的OldY方法 ‘obj.OldY()的運行結果 派生類的新方法 ‘obj.NewY()的運行結果 派生類的析構 基類的析構
“你看,你只在Main中實例化了一個派生類的對 象,為什麼先會出現‘基類的構造’?”大李問。
“這個麼,”我開始在代碼中查看起來,“是這句了。 ”我手指著派生類裡的這段代碼:
Sub New() MyBase.New() ‘注意:這句話要放在sub內的第一句 Console.WriteLine("派生類的構造") End Sub
“沒錯,我們必須要注意這一點,就是派生類的構造函 數與析構函數都必須重新編寫。New 構造函數一般用於打開文件、連接到數據庫 、初始化變量以及處理任何需要在可使用對象前完成的其他任務。我們必須在Sub New 構造函數中的第一行代碼使用語句 MyBase.New(),來調用類層次結構中該類 的基類的構造函數,以獲得基類的性質。析構則是在Sub Finalize中執行完對派 生類的的清理任務,如保存狀態信息、關閉文件和與數據庫的連接,以及執行在 釋放對象前必須完成的其他任務之後,在析構函數的最後一句使用語句 MyBase.Finalize() 顯式調用其基類的 Sub Finalize 方法,以析構MyBase.New ()構造的內容。所以你從程序運行結果中也可以很清楚的看出這一順序。” 大李敲擊著屏幕,象是給我提個醒。
“明白了,我會記著的。 ”我誠懇地點頭回應著。
大李突然想起了什麼,抬頭對我說: “講到類的繼承,我們還得看一下重載與隱藏的問題。”