熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

Java中鮮為人知的缺點(下)

2013-11-15 11:48:32  來源: JSP教程 

  最後討論一下無法繼承多種類的裝配問題該問題的原因在於Java不允許多層繼承
  
  Java不能進行多層繼承這一點大多經常作為其優點而不是缺點而被提出來C++允許多層繼承但結果卻致使程序變得非常復雜而且還產生了難以理解的錯誤
  
  多層繼承在裝配時會很復雜
  
  多層繼承會在如下幾個方面導致混亂第一是名稱的沖突在繼承具有相同名稱的其他類時不知道是哪個類的方法將會被調用(圖這一點是在一個類繼承兩個已經繼承了某一個類的類時經常發生的問題這種繼承稱為菱形繼承(圖在分別改寫(override)最上層的類的方法後就會引起被最下層的類所調用的問題
   
  圖●在需要繼承兩個具有相同名稱的方法的超級類時其名稱就會發生沖突這一點是經常被作為多層繼承的問題而指出來的地方
   
  圖●菱形繼承的一個例子在同一個人具有社會人和學生兩種性質的時候就必然會引起此類問題
  第二類的層次也會變得很復雜如果只有單繼承類的結構僅僅只會分支成樹狀而如果是多層繼承一下子就會變得很復雜如果多次反復地進行多層繼承掌握類的層次關系幾乎就將變得不可能
  
  由於Java只允許單繼承因此就不會引起這種問題不過用戶當然也希望通過將多個不同的類組合起來生成新的類為了解決這一問題Java就提供了被稱為接口的多層繼承的功能
  
  日本產業技術綜合研究所信息處理研究部的主任研究員一杉裕志說Java只允許單繼承從編程語言的裝配的角度來講是一種很不錯的作法甚至有人表示Java利用接口來取代多層繼承給人的感覺非常不錯此前Java之所以如此普及就是因為Java的語言標准采取了適當的折衷(東京大學研究生院處理理工學系研究專業專門從事計算機科學的萩谷昌己教授)
  
  接口不能繼承裝配
   
  圖●Java只允許繼承一個裝配因此就必須完整地復制代碼
  不過基於接口的偽多層繼承存在致命的缺點這就是指接口無法繼承裝配Ruby語言的開發者日本的松本幸弘指出使用接口取代多層繼承是Java的高明之處不過放棄裝配的繼承則令人非常痛心
  
  繼承個類的功能時Java將會復制某一個類的源代碼結果相同的代碼就會分散在各種不同的位置可維護性就會顯著降低(圖將相同的處理過程集中到名為類的單位中來提高面向對象的優點沒有得到充分的利用從市場銷售上來講Java是一種取得了巨大成功的語言但是從編程語言的裝配角度來看我認為它是一個失敗的作品(松本)
  
  Ruby語言利用Mixin實現裝配的繼承
  
  實際上松本開發的Ruby語言也和Java一樣只允許單繼承不過Ruby則利用相當於Java接口的方法實現了裝配的繼承這就是被稱為Mixin的方法
  
  Mixin是指僅將程序中具有再利用性的功能部分集中到被稱為模塊的單位中以供其他的類來使用模塊與類一樣其本身無法利用new運算符來生成只有include即嵌入到其他的類中才能使用(圖)
  
  LIST 就是使用了Mixin方法的簡單Ruby代碼定義了一個可以輸出test字符串的名為TestModule的模塊TestClass類嵌入了該模塊這樣一來TestClass類就可以像調用自身的方法一樣調用TestModule模塊中的方法
  
  不過Ruby的Mixin所解決的只是由多層繼承所造成的繼承關系的復雜性在多個模塊存在同名的方法時就會產生與多層繼承相同的問題Ruby優先處理由後面嵌入的方法(注
    
  圖●Ruby中的Mixin功能將集中了各種功能的模塊嵌入到類中來使用
   
   LIST ●使用Ruby中Mixin功能的代碼TestClass類可以像使用自己的方法一樣使用TestModule模塊所裝配的方法
  利用與類不同的單位進行程序再利用的MixJuice語言
  
  目前一種利用與Ruby不同的方法來提高程序的再利用性的名為MixJuice的語言也在開發之中這是一種基於Java的獨立語言
   
  LIST ●MixJuice的代碼程序以module(模塊)為單位進行描述而類則由module來分割
  為了程序的再利用即便MixJuice也使用了與類不同的編程單位這種單位與Ruby一樣被稱為模塊MixJuice語言的開發者日本產業技術綜合研究所的一杉表示在基於Java等語言中常見的類的程序設計中通過多個類的協作實現某一種功能時類就無法進行再利用因此應該有一個與類不同的可以再利用的編程單位
  
  MixJuice語言中當然也有類但是編程時所處理的並不是一個類的源代碼而是以包含了各種可協調工作的類的模塊為單位來描述程序重新利用模塊進行擴展時描述的是模塊之間的區別
  
  LIST 就是實際的源代碼程序是以模塊為單位來組織的類則在模塊中使用define關鍵詞進行定義如本例所示通過追加模塊來描述與現有類的區別把使用多個類而實現的功能集中到了一起
  
  必然引起裝配缺陷
  
  不過這種方法必然會產生其他問題就是說要使用MixJuice中的模塊來擴展類時就會產生裝配缺陷
  
  圖就是一個具體的例子模塊m和m均繼承了模塊mm定義了在m中定義的類S的派生類B而m則向S類追加了方法如果是普通的方法就不會產生問題但是這裡卻定義了一個利用派生類來強制裝配的抽象方法實際上它的派生類A添寫了裝配
  
  如要同時使用這兩個模塊連接時就會產生錯誤因為類B沒有裝配由m追加到類S中的方法m()為了解決這個問題無論是誰擁有多麼豐富的知識都必須對方法進行裝配這種問題是因模塊具有方法追加和子類(派生類)追加等種擴展的方向性而引起的(圖
   
  
  圖●裝配缺陷的例子由m追加到類S中的抽象方法的存在與m沒有任何關系如果同時使用這個模塊時就會產生編譯錯誤
  
   
  圖●存在二個以上的擴展方向性時就會產生裝配缺陷拿MixJuice來說就是子類和方法的擴展性
  提出了新的分割單位的面向側面編程(AspectOriented programming)
  
  像MixJuice語言那樣利用橫跨多個對象的單位來把握系統的觀點稱為關注分隔(Separation of ConcernsSoC)類的相互作用也屬於關注的一種這種觀點並不是僅僅單純以對象為單位還要由其他側面來分割系統
  
  最近這種觀點已經開始受到越來越廣泛的關注基於該觀點的代表性編程范式(paradigm)就是面向側面編程它就是以關注為分隔單位的如果存在多個與類相同的關注就通過將這些關注組合起來實現一種功能這種功能就是側面(Aspect)
  
  圖就是具體的例子把移動圖形來刷新畫面的處理過程定義為一個側面圖形是由點和線組成的每一個點和線中均存在移動的方法和用於設置位置的方法這些動作相互協作就可實現稱為畫面刷新的側面
  
  LIST 就是使用基於Java的面向側面語言AspectJ來描述側面的源代碼在一個被稱為移動圖形的程序段中定義了多個類的多個方法圖形的移動結束後最後執行重新刷新畫面的處理過程
   
  圖●利用關注分割的圖示點和線以及他們各自所具有的定位和移動的方法被劃分成了相同的關注該圖摘自面向側面編程的倡導者Gregor Kiczales在面向側面編程技術研討會上發表的演講資料
  
  LIST ●利用AspectJ描述側面的源代碼將用於實現圖像移動的各種類中的方法歸納為movemove結束以後執行由after描述的畫面刷新摘自Gregor Kiczales在面向側面編程技術研討會上發表的演講資料
  與面向對象並不矛盾
  
  面向側面編程在對象以外導入了分割系統的單位提高了程序的再利用性和擴展性如果只有對象單位有分割的軸也許確實就會存在一定的限制吧
  
  不過面向對象本身就是公認難度很高的編程范式盡管如此面向對象語言能夠普及到如此程序恐怕是因為只有對象單位有分割的軸正因為軸只有一個好歹才能夠理解如果還要加上被稱為側面的軸也許有很多程序員就會產生混亂
  
  另外面向側面則是自由度很高的編程范式正是因為自由度高程序員才會感到苦惱因為他們不知道應該如何分割或組織程序也就是說在某種程度上縮小自由度並給程序員提供編程指南也可以說是編程語言的任務
  
  面向側面是一種擴展了面向對象的編程范式如果認為面向對象的自由度合適就可以繼續使用它就連面向側面的倡導者加拿大英屬哥倫比亞大學的Gregor Kiczales本人也表示沒有必要非要去勉強地使用側面來編程程序員要根據自己的開發風格在追求一種易用性和擴展性適當平衡的同時使用這種編程范式
  
  
  

From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19661.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.