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

多態與面向對象(一)

2022-06-13   來源: Java核心技術 

  不管時光如何流逝應該說每個人對他職業生涯的第一次面試都是記憶猶新不是嗎?
  
  經過前兩輪的篩選我推開那扇門小心翼翼地坐在Andy面前我應聘的職位是C++程序員坦率的講我有一些緊張您知道的一個找不到工作的應屆大學生生活是如何地充滿壓力
  
  能告訴我什麼是OO嗎?Andy一開口就是這樣一句
  
  我有預感他將主要考察我在面向對象方面的編程能力我知道C++支持數種不同的程序設計風格包括面向過程的編程風格(Procedural Programming)泛型編程風格(Generic Programming)基於對象的編程風格(Objectbase Programming)和面向對象的編程風格(Objectoriented Programming)可是什麼是OO呢?具體概念我還真的不大清楚
  
  分析問題時我們常常會把事物看作一個一個的對象把具有相同特征的對象看作一個類我想他是不是在期待這樣的答案呢
  
  那你對OB又作何解釋呢?Andy面無表情
  
  對呀所謂OB就是被稱作ADT(Abstract Data Template)的程序設計風格我剛剛所說的不也被OB所支持嗎?一直以為自己在使用面向對象編程技術誰知道真是慚愧啊
  
  是的應該說OO留給我印象最深的還是繼承和多態現在我只能盡量回想我曾參與過的少得可憐的項目以尋求答案
  
  幾乎每個人都同意繼承和多態是OO概念可是據我所知真正理解這兩個概念的卻不多時間有限我們就談談多態你知道C++以哪些方法支持多態嗎?顯然他不想在我身上花太多時間
  
  這個問題對於我還是不難回答的例如有以下繼承體系
  
  其中rotate是一個虛擬函數C++ 以三種方法支持多態其一經由一組隱含的轉化操作如把一個派生類指針轉化為一個指向其公有基類類型的指針
  
  shape *ps = new circle();
  
  其二經由虛擬機制
  
  ps>rotate();
  
  其三經由dynamic_cast和typeid運算符
  
  if (circle *pc = dynamic_cast(ps))
  
  多態的主要用途是經由一個共同的接口來影響類型的封裝這個接口通常被定義在一個抽象的base class中這個接口是以virtual function機制引發的它可以在執行期根據object的真正類型解析處到底是哪一個函數實體被調用趁熱打鐵我敢肯定如果還不能趁此機多說幾句的話那將是前功盡棄
  
  如果我寫下這樣的代碼又將怎樣呢?Andy飛快地在一張紙片上寫下
  
  circle p;
  
       shape s(p);
  
       srotate();
  
  以一派生類對象為初值初始化一個基類對象!這是我的第一反應
  
  這會發生所謂的對象切割同時多態不再呈現雖然我敢肯定我所說的話語可我總感覺Andy另有它意
  
  為什麼多態不再呈現?他的眼神流露出一絲疑問
  
  因為多態的特性只有在使用pointer或reference時才能發揮我毫不猶豫的回答
  
  好吧請你講講曾參與過的設計Andy似乎已經達到目的後來我才知道C++通過class的pointer和reference來支持多態這種程序設計風格就是所謂的OO
  
  我想起曾經參與的一個項目我的主要任務是通過串口來控制一種叫做雲台的外設其實就是根據通信協議將客戶請求翻譯成相應的字符串然後通過串口發送出去看起來很簡單是嗎?不過為了爭取更大的市場我們必須盡可能多的支持不同廠商提供的不同協議並且能夠在未來方便地加入當前尚未支持的協議當時的設計就好像這樣子
  
  class CPtzHal
  
  {
  
  public:
  
       CPtzHal(CSerial *pSerial CProtocol *pProtocol);
  
       void sendCommand(int command);
  
  private:
  
       CSerial    *m_pSerial;
  
       CProtocol *m_pProtocol;
  
  };
  
  成員函數sendCommand的定義如下
  
  void CPtzHal::sendCommand(int command)
  
  {
  
       if(m_pSerial != NULL && m_pProtocol != NULL)
  
       {
  
            m_pSerial>send(m_pProtocol>getCommandString(command));
  
       }
  
  }
  
  您看我們使用CPtzHal 來接受並處理用戶的請求CProtocol 就是我們的協議類通過其成員函數getCommandString 得到指定的請求ID所對應的應該發往串口的字串CSerial實際上是串口類而CSerial::send的作用當然是把指定的字串發送出去
  
  那麼你是怎麼保證方便的添加新協議呢?Andy輕輕移了移身體
  
  如您所知CProtocol理所當然是一個基類而且我把它設計成一個抽象基類所有的具體的協議類都將從它派生我緩緩說道同時寫下以下代碼
  
  class CProtocol
  
  {
  
  public:
  
       virtual ~CProtocol(){};
  
       virtual string getCommandString(int) = ;
  
  };
  
  您看因為是一個基類其析構函數當然要聲明為virtual……
  
  等等既然析構函數什麼都不做為什麼要給它一個空的函數體?Andy開始試探我
  
  正如我剛才所說我是有義務要聲明它們的本來我也不想給出實現可是即使我同意編譯器也不會答應啊
  
  不錯Andy的首肯令我頗有些難為情
  
  至於每一個具體的協議類都必須實現在CProtocol中聲明的那些純虛函數(pure virtual function)我飛快地寫出以下代碼
  
  class CIntelProtocol : public CProtocol
  
  {
  
  public:
  
       string getCommandString(int command);
  
  };
  
  
  
  string CIntelProtocol::getCommandString(int command)
  
  {
  
       // 返回相應的字串
  
  }
  
  您看CIntelProtocol正是封裝了英特爾的協議當有新的協議加進來的時候做法就如同以上一般從CProtocol派生出一個新的協議類
  
  從Andy的表情可以看出他還算滿意作為協議類的客戶CPtzHal並不需要知道這個具體協議到底是英特爾的還是三星的說不准它是將來某個別的廠商所提供的可是這有什麼關系呢?不管這點如何改變CPtzHal壓根就不用變正是多態所帶來的好處
  
  我和Andy的對話就這樣結束了嗎?不還沒有這正如我要跟你講的有關OOP的故事還將繼續
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26229.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.