<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    GHawk

    敏捷軟件開發 讀書筆記 (4)——OO五大原則(3.LSP——里氏替換原則)

    OCP作為OO的高層原則,主張使用“抽象(Abstraction)”和“多態(Polymorphism)”將設計中的靜態結構改為動態結構,維持設計的封閉性。

    “抽象”是語言提供的功能。“多態”由繼承語義實現。

    如此,問題產生了:“我們如何去度量繼承關系的質量?”

    Liskov于1987年提出了一個關于繼承的原則“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”——“繼承必須確保超類所擁有的性質在子類中仍然成立?!币簿褪钦f,當一個子類的實例應該能夠替換任何其超類的實例時,它們之間才具有is-A關系。

    該原則稱為Liskov Substitution Principle——里氏替換原則。林先生在上課時風趣地稱之為“老鼠的兒子會打洞”。^_^

    我們來研究一下LSP的實質。學習OO的時候,我們知道,一個對象是一組狀態和一系列行為的組合體。狀態是對象的內在特性,行為是對象的外在特性。LSP所表述的就是在同一個繼承體系中的對象應該有共同的行為特征。

    這一點上,表明了OO的繼承與日常生活中的繼承的本質區別。舉一個例子:生物學的分類體系中把企鵝歸屬為鳥類。我們模仿這個體系,設計出這樣的類和關系。

     lsp-fig1.jpg

    類“鳥”中有個方法fly,企鵝自然也繼承了這個方法,可是企鵝不能飛阿,于是,我們在企鵝的類中覆蓋了fly方法,告訴方法的調用者:企鵝是不會飛的。這完全符合常理。但是,這違反了LSP,企鵝是鳥的子類,可是企鵝卻不能飛!需要注意的是,此處的“鳥”已經不再是生物學中的鳥了,它是軟件中的一個類、一個抽象。

    有人會說,企鵝不能飛很正常啊,而且這樣編寫代碼也能正常編譯,只要在使用這個類的客戶代碼中加一句判斷就行了。但是,這就是問題所在!首先,客戶代碼和“企鵝”的代碼很有可能不是同時設計的,在當今軟件外包一層又一層的開發模式下,你甚至根本不知道兩個模塊的原產地是哪里,也就談不上去修改客戶代碼了。客戶程序很可能是遺留系統的一部分,很可能已經不再維護,如果因為設計出這么一個“企鵝”而導致必須修改客戶代碼,誰應該承擔這部分責任呢?(大概是上帝吧,誰叫他讓“企鵝”不能飛的。^_^)“修改客戶代碼”直接違反了OCP,這就是OCP的重要性。違反LSP將使既有的設計不能封閉!

    修正后的設計如下:

     lsp-fig2.jpg

    但是,這就是LSP的全部了么?書中給了一個經典的例子,這又是一個不符合常理的例子:正方形不是一個長方形。這個悖論的詳細內容能在網上找到,我就不多廢話了。

    LSP并沒有提供解決這個問題的方案,而只是提出了這么一個問題。

    于是,工程師們開始關注如何確保對象的行為。1988年,B. Meyer提出了Design by Contract(契約式設計)理論。DbC從形式化方法中借鑒了一套確保對象行為和自身狀態的方法,其基本概念很簡單:

    1. 每個方法調用之前,該方法應該校驗傳入參數的正確性,只有正確才能執行該方法,否則認為調用方違反契約,不予執行。這稱為前置條件(Pre-condition)。
    2. 一旦通過前置條件的校驗,方法必須執行,并且必須確保執行結果符合契約,這稱之為后置條件(Post-condition)。
    3. 對象本身有一套對自身狀態進行校驗的檢查條件,以確保該對象的本質不發生改變,這稱之為不變式(Invariant)。

    以上是單個對象的約束條件。為了滿足LSP,當存在繼承關系時,子類中方法的前置條件必須與超類中被覆蓋的方法的前置條件相同或者更寬松;而子類中方法的后置條件必須與超類中被覆蓋的方法的后置條件相同或者更為嚴格。

    一些OO語言中的特性能夠說明這一問題:

    • 繼承并且覆蓋超類方法的時候,子類中的方法的可見性必須等于或者大于超類中的方法的可見性,子類中的方法所拋出的受檢異常只能是超類中對應方法所拋出的受檢異常的子類。
      public class SuperClass{
          
      public void methodA() throws IOException{}
      }


      public class SubClassA extends SuperClass{
          
      //this overriding is illegal.
          private void methodA() throws Exception{}
      }


      public class SubClassB extends SuperClass{
          
      //this overriding is OK.
          public void methodA() throws FileNotFoundException{}
      }

    • 從Java5開始,子類中的方法的返回值也可以是對應的超類方法的返回值的子類。這叫做“協變”(Covariant)
      public class SuperClass {
          
      public Number caculate(){
              
      return null;
          }

      }


      public class SubClass extends SuperClass{
          
      //only compiles in Java 5 or later.
          public Integer caculate(){
              
      return null;
          }

      }

    可以看出,以上這些特性都非常好地遵循了LSP。但是DbC呢?很遺憾,主流的面向對象語言(不論是動態語言還是靜態語言)還沒有加入對DbC的支持。但是隨著AOP概念的產生,相信不久DbC也將成為OO語言的一個重要特性之一。

    一些題外話:

    前一陣子《敲響OO時代的喪鐘》和《喪鐘為誰而鳴》兩篇文章引來了無數議論。其中提到了不少OO語言的不足。事實上,遵從LSP和OCP,不管是靜態類型還是動態類型系統,只要是OO的設計,就應該對對象的行為有嚴格的約束。這個約束并不僅僅體現在方法簽名上,而是這個具體行為的本身。這才是LSP和DbC的真諦。從這一點來說并不能說明“萬事萬物皆對象”的動態語言和“C++,Java”這種“按接口編程”語言的優劣,兩類語言都有待于改進。莊兄對DJ的設想倒是開始引入DbC的概念了。這一點還是非常值得期待的。^_^
    另外,接口的語義正被OCP、LSP、DbC這樣的概念不斷地強化,接口表達了對象行為之間的“契約”關系。而不是簡單地作為一種實現多繼承的語法糖。

    posted on 2006-01-18 18:12 GHawk 閱讀(3974) 評論(2)  編輯  收藏 所屬分類: 軟件過程 、學習筆記

    評論

    # re: 敏捷軟件開發 讀書筆記 (4)——OO五大原則(3.LSP——里氏替換原則) 2006-01-19 11:08 zhouap

    生動,解釋得夠清晰  回復  更多評論   

    # re: 敏捷軟件開發 讀書筆記 (4)——OO五大原則(3.LSP——里氏替換原則) 2006-03-01 22:31 larry

    “林先生”??莫非是也是上海交大的??  回復  更多評論   

    主站蜘蛛池模板: 一个人免费观看视频在线中文| 亚洲va乱码一区二区三区| 亚洲国产一区二区三区在线观看| 2021在线永久免费视频| 亚洲AV无码国产精品色午友在线| 你懂得的在线观看免费视频| 亚洲色大成网站WWW久久九九 | 国产综合成人亚洲区| 在线jyzzjyzz免费视频| 亚洲经典千人经典日产| 国产又长又粗又爽免费视频| 国产天堂亚洲国产碰碰| 亚洲毛片av日韩av无码| 日韩精品无码免费专区午夜| 亚洲国产精品无码成人片久久| 国产三级在线免费| 91精品国产亚洲爽啪在线观看| 最近2018中文字幕免费视频| 亚洲AV成人噜噜无码网站| 成年女人毛片免费观看97| 少妇亚洲免费精品| 国产V亚洲V天堂无码久久久| 91精品免费观看| 亚洲中文字幕久久无码| 免费在线一级毛片| a视频免费在线观看| 亚洲黄色在线网站| 免费看片A级毛片免费看| 无码毛片一区二区三区视频免费播放 | 亚洲人6666成人观看| 四虎影视在线永久免费看黄| 国产午夜无码片免费| 亚洲最大视频网站| 波多野结衣视频在线免费观看| 久久免费99精品国产自在现线| 久久久亚洲欧洲日产国码是AV| 女人毛片a级大学毛片免费| 国产免费区在线观看十分钟 | 四虎永久免费观看| 免费黄色电影在线观看| 亚洲精品无码久久久久秋霞|