国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

我看多態——多態的學習筆記

2019-11-18 13:09:07
字體:
來源:轉載
供稿:網友

  發現好多初學的朋友對多態部分總是比較模糊,小弟今天在看朋友的學習筆記的時候也發現這個問題,所以借我朋友筆記上的問題,發表一下自己的看法,先假設有繼續關系如下的類: 代碼:
  
  Animal
  
  Mammal
  
  ---------------------------------------------------------------
  
  Dog Cat Raccoon SwampThing
  (implements (implements
  Washer) Washer)
  ? interface Washer {}
  ? class Animal {}
  ? class Mammal extends Animal {}
  ? class Dog extends Mammal {}
  ? class Cat extends Mammal implements Washer {}
  ? class Raccoon extends Mammal implements Washer {}
  ? class SwampThing extends Mammal {}
  
  下面的為對這幾個類的應用和我朋友的筆記:
  
  public class Test14 {
  public static void main(String[] a) {
  //----------------------------------
  Dog rover,fido;
  Animal anim;
  rover =new Dog();
  anim=rover; //理解成Animal anim = new Dog();
  fido =(Dog)anim; //這段話能夠通過編譯和運行!!!!!
  //fido =anim;不能通過編譯
  //----------------------------------
  Washer wawa=new Cat();
  SwampThing pogo;
  pogo=(SwampThing)wawa;
  //這句話能夠通過編譯,但不能運行
  //兩個毫不相干的類對象,居然能夠通過編譯?
  //經另外測試,任意兩個不相干的類對象cast是會出現編譯錯誤的,
  //所以,上面的類可能是繼續了同一個類的緣故?
  
  我的解釋:
  首先,我們知道,超類類型的變量可以引用一個子類類型的對象,即
  代碼:
  Animal anim = new Dog();
  這樣是完全可以的,但是要注重的是編譯器只檢查且承認定義時候的類型,所以這樣定義并賦值的anim變量不能調用Dog類中特有的實例字段和方法,這就是我們通常所說的隱藏,假如我們仍然要用到這些被隱藏的東西怎么辦呢,那就是后面我們看到的筆者認為費解的那句:
  代碼:
  fido =(Dog)anim;
  其實這樣只是恢復了被隱藏的功能,并不是把超類對象賦給子類變量,當然,編譯器并不管最終這個造型轉換能否成功,編譯器現在只知道你在把一個Dog型的對象賦值給一個Dog型的變量,這當然沒有問題,同樣,后面的這樣3句
  代碼:
  Washer wawa=new Cat();
  SwampThing pogo;
  pogo=(SwampThing)wawa;
  
  也很好理解,編譯器只知道你在試圖把一個SwampThing型的對象賦值給一個SwampThing型的變量,這當然沒問題,注重對象wawa原來是什么類型編譯器并不管(這句話并不全面,具體見下面),它只知道不管什么類型已經強制轉換成了SwampThing型,至于這種轉換會否成功則會在運行時判定,假如不能成功轉換當然會拋出異常,這就是為什么總說造型前請用instanceof判定對象本身是否屬于要轉換的類!
  讓我們探討的再深一點:
  注重筆者上邊最后注釋的話是不對的,
  Cat類與SwampThing類不是毫不相干的,它們都實現了Washer接口,注重變量wawa被定義的類型并不是Cat類型,而是Washer接口類型,所以
  代碼:
  pogo=(SwampThing)wawa;
  
  這句話才有可能成功,假如變量wawa被定義為Cat類型,則上面的造型絕對不可能成功,即編譯也無法通過!由此我們知道,編譯器也會為造型做出判定,不過編譯器只會判定被造型的對象有沒有可能被造型成功,就象上面的代碼,wawa定義的時候是Washer類型,任何實現了這個接口的類的對象都可以被wawa引用,而SwampThing類也實現了這個接口,所以當編譯器執行到上面的代碼時,編譯器只通過對wawa的定義檢查,認為wawa有可能指向SwampThing類型的對象,這個造型有可能成功,所以可以被編譯成功!
  還可以再深一點討論:
  上面例子中筆者注釋了這么一句話:
  //fido =anim;不能通過編譯
  通過閱讀之前的代碼我們知道變量anim指向的實際對象和fido的定義類型是一致的,都是Dog,但是不能編譯,這是因為編譯器只檢查anim的定義,發現是Dog的超類,所以我們必須要先類型轉換,但是假設可以通過某種方法強制通過編譯,那么這句話運行時反而沒有問題因為實際類型是匹配的,這種情況可以說正好與上面討論的能通過編譯但是運行出錯的情況相反!
  總結:正是java中編譯器只檢查定義類型,運行時檢查實際類型的雙重檢查方式造成了面向對象中多態這種即規范同時又非常有靈活性的機制

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 天台县| 沧州市| 邳州市| 玛多县| 乐亭县| 马山县| 石家庄市| 信阳市| 措勤县| 柞水县| 玛曲县| 镇宁| 赣州市| 汽车| 深州市| 柘荣县| 贺兰县| 西乌珠穆沁旗| 敦化市| 永安市| 晋江市| 乌拉特后旗| 尼勒克县| 项城市| 清流县| 台中市| 开阳县| 屏南县| 神木县| 万盛区| 磐安县| 稷山县| 麟游县| 青州市| 石景山区| 清流县| 张家口市| 贡山| 凌海市| 滦南县| 中江县|