熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

多形對象的互換使用

2013-11-23 18:43:38  來源: Java核心技術 

  通常繼承最終會以創建一系列類收場所有類都建立在統一的接口基礎上我們用一幅顛倒的樹形圖來闡明這一點(見注釋)
  [注釋] 這兒采用了統一記號法
  
  對這樣的一系列類我們要進行的一項重要處理就是將衍生類的對象當作基礎類的一個對象對待這一點是非常重要的因為它意味著我們只需編寫單一的代碼令其忽略類型的特定細節只與基礎類打交道這樣一來那些代碼就可與類型信息分開所以更易編寫也更易理解此外若通過繼承增添了一種新類型三角形那麼我們為幾何形狀新類型編寫的代碼會象在舊類型裡一樣良好地工作所以說程序具備了擴展能力具有擴展性
  以上面的例子為基礎假設我們用Java寫了這樣一個函數
  void doStuff(Shape s) {
  serase();
   //
 sdraw();
}
  這個函數可與任何幾何形狀(Shape)通信所以完全獨立於它要描繪(draw)和刪除(erase)的任何特定類型的對象如果我們在其他一些程序裡使用doStuff()函數
  Circle c = new Circle();
Triangle t = new Triangle();
Line l = new Line();
doStuff(c);
doStuff(t);
doStuff(l);
  那麼對doStuff()的調用會自動良好地工作無論對象的具體類型是什麼
  這實際是一個非常有用的編程技巧請考慮下面這行代碼
  doStuff(c);
  此時一個Circle(圓)句柄傳遞給一個本來期待Shape(形狀)句柄的函數由於圓是一種幾何形狀所以doStuff()能正確地進行處理也就是說凡是doStuff()能發給一個Shape的消息Circle也能接收所以這樣做是安全的不會造成錯誤
  我們將這種把衍生類型當作它的基本類型處理的過程叫作Upcasting(上溯造型)其中cast(造型)是指根據一個現成的模型創建Up(向上)表明繼承的方向是從上面來的——即基礎類位於頂部而衍生類在下方展開所以根據基礎類進行造型就是一個從上面繼承的過程Upcasting
  在面向對象的程序裡通常都要用到上溯造型技術這是避免去調查准確類型的一個好辦法請看看doStuff()裡的代碼
  serase();
//
sdraw();
  注意它並未這樣表達如果你是一個Circle就這樣做如果你是一個Square就那樣做等等若那樣編寫代碼就需檢查一個Shape所有可能的類型如圓矩形等等這顯然是非常麻煩的而且每次添加了一種新的Shape類型後都要相應地進行修改在這兒我們只需說你是一種幾何形狀我知道你能將自己刪掉即erase()請自己采取那個行動並自己去控制所有的細節吧
   動態綁定
  在doStuff()的代碼裡最讓人吃驚的是盡管我們沒作出任何特殊指示采取的操作也是完全正確和恰當的我們知道為Circle調用draw()時執行的代碼與為一個Square或Line調用draw()時執行的代碼是不同的但在將draw()消息發給一個匿名Shape時根據Shape句柄當時連接的實際類型會相應地采取正確的操作這當然令人驚訝因為當Java編譯器為doStuff()編譯代碼時它並不知道自己要操作的准確類型是什麼盡管我們確實可以保證最終會為Shape調用erase()為Shape調用draw()但並不能保證為特定的CircleSquare或者Line調用什麼然而最後采取的操作同樣是正確的這是怎麼做到的呢?
  將一條消息發給對象時如果並不知道對方的具體類型是什麼但采取的行動同樣是正確的這種情況就叫作多形性(Polymorphism)對面向對象的程序設計語言來說它們用以實現多形性的方法叫作動態綁定編譯器和運行期系統會負責對所有細節的控制我們只需知道會發生什麼事情而且更重要的是如何利用它幫助自己設計程序
  有些語言要求我們用一個特殊的關鍵字來允許動態綁定在C++中這個關鍵字是virtual在Java中我們則完全不必記住添加一個關鍵字因為函數的動態綁定是自動進行的所以在將一條消息發給對象時我們完全可以肯定對象會采取正確的行動即使其中涉及上溯造型之類的處理
   抽象的基礎類和接口
  設計程序時我們經常都希望基礎類只為自己的衍生類提供一個接口也就是說我們不想其他任何人實際創建基礎類的一個對象只對上溯造型成它以便使用它們的接口為達到這個目的需要把那個類變成抽象的——使用abstract關鍵字若有人試圖創建抽象類的一個對象編譯器就會阻止他們這種工具可有效強制實行一種特殊的設計
  亦可用abstract關鍵字描述一個尚未實現的方法——作為一個使用指出這是適用於從這個類繼承的所有類型的一個接口函數但目前尚沒有對它進行任何形式的實現抽象方法也許只能在一個抽象類裡創建繼承了一個類後那個方法就必須實現否則繼承的類也會變成抽象通過創建一個抽象方法我們可以將一個方法置入接口中不必再為那個方法提供可能毫無意義的主體代碼
  interface(接口)關鍵字將抽象類的概念更延伸了一步它完全禁止了所有的函數定義接口是一種相當有效和常用的工具另外如果自己願意亦可將多個接口都合並到一起(不能從多個普通class或abstract class中繼承)
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25632.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.