程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB.NET >> VB.NET之旅(七)—脆弱的基類

VB.NET之旅(七)—脆弱的基類

編輯:VB.NET

“既然說是脆弱,當然是指它象蛋殼一樣不堪一擊喽。這個問題其實很 好理解。程序總是由人來設計與編寫的,所以工作開始時考慮不到某些問題當然 也是很正常的事。所以可能在工作進行了一段時間後發現基類需要變更。你想, 如果我在基類中更改了成員的數據類型,以及那些允許重寫的那些方法和屬性, 那派生類及其子類還能正常工作嗎?尤其是當一個團隊中的多個開發人員一起來 創作基類和派生類時,就更是要命了。很多情況下,大家可能已經把基類和一些 派生類編譯成二進制形式進行提交了。更改基類,重新編譯再分布,會牽一發而 動全身,導致項目的崩潰。所以我們把這叫做‘脆弱的基類’。也就 是說,它是整個工程中最薄弱最致命的環節。”大李眉頭一直緊鎖著,想必 是回想起了自己受打擊的經歷。

“這麼嚴重呀,現在的軟件工程設 計方法會不會對這個有很好的解決方案?”我努力想緩解一下大李的嚴肅神 情。

“如果對項目的前期設計考慮盡可能周詳,在工程實施中對項目的代碼 控制與相關性分析做得踏實,會起到很好的效果。但是不管一個人如何努力,有 時還是無法避免對基類進行不可預見的更改。我們摸索過很久,有了一些處理的 手段。”

“真是成事在人呀,我們現在有什麼解決之道? ”我也一下子振奮起來了。

“呵呵,並不是什麼完美解決方案 。只能在某種程度上減輕危害。我們常用的一個方法,最直接的思想就是,把有 可能發生的更改全都放在派生類中進行,不在基類中做。”

“ 這具體是什麼意思呀,我還是不太明白。”我不好意思地撓撓頭。

大李微笑著點點頭,看來是知道我不會明白的了。“我們在基類中使用的是 抽象類,它內含的方法與屬性只有定義,沒有進行實現,而把實現部分都放在派 生類中做。這樣一來,抽象類自身是無法被實例化的。但是它的好處不言而喻, 就是有可能發生的實現上的更改都會只涉及到它的派生類了。VB.NET中就提供了 這樣的手段。”

說著,大李就打開VS.NET集成編譯環境,順手寫了 一小段代碼:

Public MustInherit Class CBaseHenry 
 
  Public MustOverride Sub subX(ByVal x As Integer) 
 
  Public MustOverride Function fcnY(ByVal y As Integer) As 

Long 
 
End Class 
 
Public Class CDerivedHenry 
 
  Inherits CBaseHenry 
 
  Public Overrides Sub subX(ByVal x As Integer) 
 
    '寫入實現的代碼 
 
  End Sub 
 
  Public Overrides Function fcnY(ByVal y As Integer) As Long

 
 
    '寫入實現的代碼 
 
  End Function 
 
End Class

“這裡要注意兩個問題,一個是關鍵字,我們用 MustInherit來修飾類名,使類成為抽象類,在它的成員中,把方法和屬性前加入 MustOverride修飾符表示它們必須在派生類中加以實現。第二個要注意的是,派 生類必須對所有用MustOverride標識的基類方法和屬性都進行實現,只重寫了 subX,不寫fcnY編譯器會報錯的。”

“這的確可以解決一部分 問題,但好象只能解決在基類中進行實現的代碼有更改的問題,對於數據類型的 更改好象沒有什麼效果。”我看了好一會,發出了這樣的疑問。

“所以我剛才說,是在某種程度上進行解決嘛。”大李也不由 笑了起來,“不過你提的這個問題,倒不是太麻煩,我們可以在派生類中用 Shadows來解決呀!(詳見本報上一期《重載與隱藏》)”

這倒是個 不錯的主意,我心中暗暗評價了一番。突然我又想到一個問題:“如果基類 要做功能擴展,怎麼辦呀?”

“如果是要做擴展,最安全的方 法是添加新成員,而不是對基類的大肆修改。一般是往派生類添加設計時缺失的 新成員。最好不要使用Overloads關鍵字來命名與基類相同的成員,那樣往往會帶 給你意想不到的問題。最好重新定義新成員,命名上也要盡量與基類已有的成員 名區分開來。其實,也可以往抽象類基類中添加新成員的定義,但這樣一來,需 要為基類制定版本,雖然不會對應用程序造成毀滅性的危害,但是應該要能夠完 全地控制與管理自己的代碼。我們一般是不希望擴展基類的。”

我 已經大意上領會了大李的一片苦心:“您的意思,是不是指基類的脆弱問題 實際上是客觀存在的,我們所做的就是要最大程度的減小這個問題帶來的危害? ”

大李眼中閃過一絲贊許的笑意,颌首道:“沒錯,對於一個 應用程序的設計者來講,想使用面向對象方法來開發,必須要在設計的時候精心 策劃類的層次結構。一般來說,是有這樣幾個准則需要把握的:

第一,遵 循先通用,再專用的原則。先設計好層次結構中每一級別的類中的通用部分,也 就是提供給派生類繼承的成員和標識為Public的成員;

第二,在定義數據 類型和存儲區時要有預留量,以避免以後更改困難。例如,即使當前數據可能僅 需要Integer類型就夠了,在設計時我們使用 Long 類型的變量。當然,最好能物 盡其用,也不要盲目放大;

第三,在一個項目中,必須統一管理與分配團 隊中使用的所有的命名,以減少命名沖突,這一點其實事關重大;

第四, 要使用提供可行的最低訪問權限的訪問修飾符聲明類成員。內部類成員應聲明為 Private;僅在類內與派生類才需要的成員應標記為Protected;Friend 數據成員 可以從類的外部訪問,但僅限於該模塊是定義該類的項目的一個組成部分;使用 Public標識的成員,只能是實例化時真正需要的內容,而且經常用在類層次結構 的底部。”

“也就是說,一個規范的操作,標准的命名體系可 以決定基類的強壯與否?”我不禁感觸了一聲。

“不對,應該 這樣說,可以決定的是給脆弱的基類穿上多厚的防護衣。因為基類始終都是脆弱 的。”大李更正道。

我連聲贊同:“對,對。我現在是真正明 白為什麼總有人提編程規范的事情,我一直認為是增強代碼的可讀性,沒想到, 對程序自身還有這麼大的幫助。”

“當然,其實你認真想一下 ,Overrides關鍵字的作用,不管要不要注明,編譯器都可以很方便地判斷方法或 屬性是否在基類中,簽名是否匹配,但是VB.NET要求我們必須標注,就是強制開 發人員注明重載基類方法或屬性的意圖,使開發過程更合理與有效。此外,還有 更重要的就是,我們要在工程實踐中不斷地學習與磨練,了解更多的知識,獲得 更多的經驗,這樣才會成長為一名合格的程序設計師。就拿繼承來說吧,在.NET 中其實支持三種繼承方式:實現繼承、接口繼承、可視繼承。我們其實只用了第 一種繼承方式,你看,要學的東西是不是很多?”大李友好地拍了拍我的肩 膀。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved