邊城愚人

          如果我不在邊城,我一定是在前往邊城的路上。

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            31 隨筆 :: 0 文章 :: 96 評(píng)論 :: 0 Trackbacks

          ??? ??? 題按:做了幾年的java程序,卻很難說對(duì)基本的OO概念都有理解。即便每天都寫的代碼中,也很難說清楚其中到底運(yùn)用了怎樣的概念和思想。前日的考試中看到關(guān)于上溯造型與下溯造型的問題,就查了些資料,集中說一下吧。

          ??? ??? 先給出個(gè)例子,代碼如下:

          package ?casting;
          public ? abstract ? class ?Animal?{
          ????
          public ? abstract ? void ?speak();
          ????
          public ? void ?eat(){
          ????????
          // 悶頭吃,不做額外的事情
          ????}
          }

          package ?casting;

          public ? interface ?DoorGod?{
          ????
          void ?guard();
          }


          package ?casting;

          public ? class ?Cat? extends ?Animal?{

          ????@Override
          ????
          public ? void ?eat()?{
          ????????
          try ?{
          ????????????Thread.sleep(
          1000 );
          ????????}?
          catch ?(InterruptedException?e)?{
          ????????????e.printStackTrace();
          ????????}
          ????????
          super .eat();
          ????}

          ????@Override
          ????
          public ? void ?speak()?{
          ????????System.out.println(
          " 喵喵 " );
          ????}

          }

          package ?casting;

          public ? class ?Dog? extends ?Animal? implements ?DoorGod{

          ????@Override
          ????
          public ? void ?speak()?{
          ????????System.out.println(
          " 汪汪 " );
          ????}

          ????
          public ? void ?guard()?{
          ????????
          while ( true ){
          ????????????System.out.println(
          " 汪汪 " );
          ????????}
          ????}
          ????
          }

          ???? 其中Animal為基類,定義speakeat方法,eat方法給出了空實(shí)現(xiàn); DoorGod為門神接口,定義了 guard方法來守護(hù)家門; Cat為繼承Animal的子類,這里假定貓有挑食的習(xí)慣,在eat中要耽擱點(diǎn)時(shí)間看看伙食;Dog也為繼承Animal的子類,同時(shí)它實(shí)現(xiàn)了DoorGod接口來守護(hù)家門。

          ??? ??? 先說說上溯造型(upcasting)。這個(gè)術(shù)語緣于繼承關(guān)系圖的傳統(tǒng)畫法:將基類至于頂部,而向下發(fā)展的就是派生類。根據(jù)上面的sample,我給出下面的一個(gè)小應(yīng)用:


          package?casting;

          public?class?Main?{

          ????
          public?static?void?upcasting(Animal?animal){
          ????????animal.speak();
          ????????animal.eat();
          ????}
          ????
          public?static?void?main(String[]?args)?{
          ????????Animal?dog1?
          =?new?Dog();
          ????????upcasting(dog1);
          ????????
          ????????Dog?dog2?
          =?new?Dog();
          ????????upcasting(dog2);
          ????}

          }

          ??? ??? 由于upcasting(Animal animal)方法的參數(shù)是 Animal類型的,因此如果傳入的參數(shù)是 Animal的子類,傳入的參數(shù)就會(huì)被轉(zhuǎn)換成父類Animal類型,這樣你創(chuàng)建的Dog對(duì)象能使用的方法只是Animal中的簽名方法;也就是說,在上溯的過程中,Dog的接口變窄了,它本身的一些方法(例如實(shí)現(xiàn)了 DoorGodguard方法)就不可見了。如果你想使用Dog中存在而Animal中不存在的方法(比如guard方法),編譯時(shí)不能通過的。由此可見,上溯造型是安全的類型轉(zhuǎn)換。另一方面,雖然upcasting(Animal animal)方法的參數(shù)是 Animal類型,但傳入的參數(shù)可以是Animal的派生類(這也是OO編程中慣用的編程方法),這里面就有個(gè)對(duì)象的類型識(shí)別問題,也就是運(yùn)行時(shí)類型識(shí)別(run-time type identification,縮寫為RTTI) ,這也可以單獨(dú)寫一篇文章了,《Thinking in Java》中的第10章詳細(xì)地闡述了RTTI。

          ??? ??? 相對(duì)于類型轉(zhuǎn)換安全的上溯造型,下溯造型就未必是安全的了。我們經(jīng)常會(huì)做些強(qiáng)制類型轉(zhuǎn)換的事情,有時(shí)我們也會(huì)無意間遇到 ClassCastException的轉(zhuǎn)換異常(從這一點(diǎn)來說,我們應(yīng)該多用范型來避免不安全的類型轉(zhuǎn)換)。例如:


          public?static?void?downcasting(Animal?animal){
          ????????
          //DoorGod?doorGod?=?(DoorGod)animal;
          ????????if(animal?instanceof?DoorGod){
          ????????????DoorGod?doorGod?
          =?(DoorGod)animal;
          ????????????doorGod.guard();
          ????????}
          ????????
          if(animal?instanceof?Cat){
          ????????????Cat?cat?
          =?(Cat)animal;
          ????????????cat.speak();
          ????????}

          } ???

          如果沒有采取措施(上面使用的措施是instanceof)判斷對(duì)象的類型,那么向下的強(qiáng)制轉(zhuǎn)換就是不安全的。這種轉(zhuǎn)換錯(cuò)誤在編譯時(shí)是不能檢測(cè)出來的,只有在運(yùn)行時(shí)才會(huì)拋出 ClassCastException異常,對(duì)于測(cè)試來說,這樣的錯(cuò)誤也是很難檢測(cè)的。

          總的來說,上溯造型與下溯造型概念上還是很簡(jiǎn)單的。但即便最簡(jiǎn)單的東西,我們也有可能犯下錯(cuò)誤。用了那么多的框架后,回頭看看基礎(chǔ)知識(shí),發(fā)現(xiàn)自己的根基并不是想象中的牢固阿。

          注:本文參考了Thinking in Java》,這本書真需要細(xì)細(xì)品味?。?/font>





          posted on 2007-05-21 22:34 kafka0102 閱讀(3192) 評(píng)論(2)  編輯  收藏 所屬分類: J2SE

          評(píng)論

          # re: 上溯造型和下溯造型 2007-05-22 09:07 自己的小屋
          這里是upcasting和downcasting...它應(yīng)該是繼承的一些特征。設(shè)計(jì)模式中就瘋狂得用到這些東西。比如說還有:多態(tài)等。  回復(fù)  更多評(píng)論
            

          # re: 上溯造型和下溯造型 2007-05-22 23:52 熱門單曲
          多謝樓主分享 頂了  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 酒泉市| 尼玛县| 寻乌县| 冀州市| 河东区| 阿荣旗| 墨脱县| 辛集市| 芦溪县| 武汉市| 米泉市| 苏尼特左旗| 墨玉县| 收藏| 清流县| 讷河市| 吉林省| 法库县| 无极县| 安新县| 礼泉县| 金堂县| 宁化县| 阿拉尔市| 五华县| 龙井市| 庆城县| 夏津县| 乌苏市| 东宁县| 班戈县| 乾安县| 长垣县| 册亨县| 图片| 林西县| 阳春市| 沾益县| 汉阴县| 广灵县| 镇平县|