Java多態(tài)

所謂多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時并不確定董虱,而是在程序運行期間才確定,即一個引用變量到底指向哪個類的實例對象,該引用變量發(fā)出的方法調(diào)用到底是哪個類中實現(xiàn)的方法惩坑,必須由程序運行期間才能決定。因為在程序運行時才能確定具體的類也拜,這樣以舒,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實現(xiàn)上慢哈,從而導致該引用調(diào)用的具體方法隨之改變蔓钟,即不修改程序代碼就可以改變程序運行時所綁定的具體代碼,讓程序可以選擇多個運行狀態(tài)卵贱,這就是多態(tài)性滥沫。
比如你是一個酒神,對酒情有獨鐘键俱。某日回家發(fā)現(xiàn)桌上有幾個杯子里面都裝了白酒兰绣,從外面看我們是不可能知道這是些什么酒,只有喝了之后才能夠猜出來是何種酒编振。你一喝缀辩,這是劍南春、再喝這是五糧液、再喝這是酒鬼酒….在這里我們可以描述成如下:

酒 a = 劍南春
酒 b = 五糧液
酒 c = 酒鬼酒

這里所表現(xiàn)的的就是多態(tài)臀玄。劍南春瓢阴、五糧液、酒鬼酒都是酒的子類健无,我們只是通過酒這一個父類就能夠引用不同的子類炫掐,這就是多態(tài)——我們只有在運行的時候才會知道引用變量所指向的具體實例對象。
誠然睬涧,要理解多態(tài)我們就必須要明白什么是“向上轉(zhuǎn)型”募胃。在繼承中我們簡單介紹了向上轉(zhuǎn)型,這里就在啰嗦下:在上面的喝酒例子中畦浓,酒(Win)是父類痹束,劍南春(JNC)、五糧液(WLY)讶请、酒鬼酒(JGJ)是子類祷嘶。我們定義如下代碼:
JNC a = new JNC();
對于這個代碼我們非常容易理解無非就是實例化了一個劍南春的對象嘛!但是這樣呢夺溢?

  Wine a = new JNC();

在這里我們這樣理解论巍,這里定義了一個Wine 類型的a,它指向JNC對象實例风响。由于JNC是繼承與Wine嘉汰,所以JNC可以自動向上轉(zhuǎn)型為Wine,所以a是可以指向JNC實例對象的状勤。這樣做存在一個非常大的好處鞋怀,在繼承中我們知道子類是父類的擴展,它可以提供比父類更加強大的功能持搜,如果我們定義了一個指向子類的父類引用類型密似,那么它除了能夠引用父類的共性外,還可以使用子類強大的功能葫盼。
但是向上轉(zhuǎn)型存在一些缺憾残腌,那就是它必定會導致一些方法和屬性的丟失,而導致我們不能夠獲取它們贫导。所以父類類型的引用可以調(diào)用父類中定義的所有屬性和方法抛猫,對于只存在與子類中的方法和屬性它就望塵莫及了---1。

public class Animal {
    public void sleep() {
        System.out.println("父類:動物都是要睡覺");
    }
}
public class Cat extends Animal {
    public void sleep() {
        System.out.println("子類:貓跟動物的睡姿是不一樣的");
    }
    public void action(String name) {
        System.out.println("子類: 貓能爬樹");
    }
}
public static void main(String args[]) {

    Cat cat = new Cat();
    cat.sleep();
    cat.action();

    Animal a2 = new Cat();
    a2.sleep();
    a2.action();
}

改程序運行錯誤,報錯信息:

Test.java:20: 錯誤: 找不到符號
                a2.action();
                ^
  符號:   變量 a2
  位置: 類 Test
1 個錯誤

上面的代碼父類a2脱盲,在調(diào)用action()方法的時候邑滨,由于父類沒有action()方法,調(diào)用不了钱反。

多態(tài)的總結(jié)

指向子類的父類引用由于向上轉(zhuǎn)型了掖看,它只能訪問父類中擁有的方法和屬性匣距,而對于子類中存在而父類中不存在的方法,該引用是不能使用的哎壳,盡管是重載該方法毅待。若子類重寫了父類中的某些方法,在調(diào)用該些方法的時候归榕,必定是使用子類中定義的這些方法(動態(tài)連接尸红、動態(tài)調(diào)用)。

對于面向?qū)ο蠖陨残梗鄳B(tài)分為編譯時多態(tài)和運行時多態(tài)外里。其中編譯時多態(tài)是靜態(tài)的,主要是指方法的重載特石,它是根據(jù)參數(shù)列表的不同來區(qū)分不同的函數(shù)盅蝗,通過編譯之后會變成兩個不同的函數(shù),在運行時談不上多態(tài)姆蘸。而運行時多態(tài)是動態(tài)的墩莫,它是通過動態(tài)綁定來實現(xiàn)的,也就是我們所說的多態(tài)性逞敷。

Java實現(xiàn)多態(tài)存在三個必要條件:

  1. 繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類
  2. 重寫:子類對父類中某些方法進行重新定義狂秦,在調(diào)用這些方法時就會調(diào)用子類的方法。
  3. 向上轉(zhuǎn)型:在多態(tài)中需要將子類的引用賦給父類對象推捐,只有這樣該引用才能夠具備技能調(diào)用父類的方法和子類的方法
    比如:Parent p = new Child();

只有滿足上述三個條件裂问,我們才能夠在同一個繼承結(jié)構(gòu)中使用同一的邏輯實現(xiàn)代碼處理不同的對象,從而達到執(zhí)行不同的行為玖姑。
對于 Java 而言愕秫,多態(tài)實現(xiàn)機制遵循一個原則:當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法焰络,但是這個被調(diào)用的方法必須具有超類中定義過的也就是說唄子類覆蓋的方法。

多態(tài)的機制

多態(tài)的機制分為兩種:

  • 編譯時多態(tài)(又稱靜態(tài)多態(tài))
  • 運行時多態(tài)(又稱動態(tài)多態(tài))

我們通常所說的多態(tài)指的都是運行時多態(tài)符喝,也就是編譯時不確定究竟調(diào)用哪個具體方法闪彼,一直延遲到運行時才能確定。這也是為什么有時候多態(tài)方法又被稱為延遲方法的原因协饲。

多態(tài)的實現(xiàn)

在Java中有可以使用繼承和接口來實現(xiàn)多態(tài)畏腕。

基于繼承(extends)實現(xiàn)的多態(tài)

基于繼承的實現(xiàn)機制主要表現(xiàn)在父類和繼承該父類的一個或多個子類對某些方法的重寫,多個子類對同一方法的重寫可以變現(xiàn)出不同的行為茉稠。

public class Animal {
    public void sleep() {
        System.out.println("父類:動物都是要睡覺");
    }
        public void action() {
        System.out.println("動物的行為");
    }
}
public class Cat extends Animal {
    public void sleep() {
        System.out.println("子類:貓跟動物的睡姿是不一樣的");
    }
    public void action(String name) {
        System.out.println("子類: 貓能爬樹");
    }
}
public static void main(String args[]) {
    Animal a2 = new Cat();
    a2.sleep();
    a2.action();
}

在上面的代碼中父類引用子類對象,調(diào)用的是子類重寫的方法,進行輸出

基于繼承實現(xiàn)的多態(tài)總結(jié):對于引用子類的父類,在處理該引用時,它適用于繼承該父類的所有子類,子類對象的不同,對方法的實現(xiàn)也就不同,執(zhí)行相同動作產(chǎn)生的行為也就不同.

如果父類是抽象類,那么子類必須要實現(xiàn)父類中所有的抽象方法,這樣該父類所有的子類一定存在統(tǒng)一的對外接口,但其內(nèi)部的具體實現(xiàn)可以各異.這樣我們就可以使用頂層類提供的統(tǒng)一接口來處理該層次的方法.

基于接口實現(xiàn)的多態(tài)

繼承是通過重寫父類的同一方法的幾個不同子類來體現(xiàn)的,那么接口就是通過實現(xiàn)接口并覆蓋接口中同一方法的不同的類的體現(xiàn).
在接口的多態(tài)中.指向接口的引用必須是指定這實現(xiàn)了該接口的一個類的實例程序,在運行時,根據(jù)對象引用的實際類型來執(zhí)行對應的方法
繼承都是單繼承,只能為一組相關(guān)的類提供一致的服務接口,但是接口可以是多繼承多實現(xiàn),它能夠利用一組相關(guān)或者不相關(guān)的接口進行組合與擴充,能夠?qū)ν馓峁┮恢碌姆战涌?所以它相對于繼承來說有更好的靈活性.

多態(tài)的優(yōu)點

  1. 消除類型之間的耦合關(guān)系
  2. 可替換性(substitutability): 多態(tài)對已存在代碼具有可替換性.
  3. 可擴充性
  4. 接口性
  5. 靈活性
  6. 簡化性

當使用多態(tài)方式調(diào)用方法時描馅,首先檢查父類中是否有該方法,如果沒有而线,則編譯錯誤铭污;如果有恋日,在去調(diào)用子類的同同名方法。
多態(tài)的好處:可以使程序有良好的擴展嘹狞,并可以對所有類的對象進行通用處理岂膳。

經(jīng)典實例

class A{
    public String show(D obj){ 
        return ("A and D"); 
    }
    public String show(A obj){ 
        return ("A abd A");
    }
}

class B extends A{
    public String show(B obj){
        return ("B and B");
    }
    public String show(A obj){
        return ("B and A");
    }
}

class C extends B{ }

class D extends B{ }

問題:以下輸出結(jié)果是什么?
public class Test {
        public static void main(String[] args) {
                A a1 = new A();
                A a2 = new B();
                B b = new B();
                C c = new C();
                D d = new D();
        }
}

運行結(jié)果

System.out.println(a1.show(b)); ① A and A
System.out.println(a1.show(c)); ② A and A
System.out.println(a1.show(d)); ③ A and D
System.out.println(a2.show(b)); ④ B and A
System.out.println(a2.show(c)); ⑤ B and A
System.out.println(a2.show(d)); ⑥ A and D
System.out.println(b.show(b));  ⑦ B and B
System.out.println(b.show(c));  ⑧ B and B
System.out.println(b.show(d));  ⑨ A and D
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末磅网,一起剝皮案震驚了整個濱河市谈截,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涧偷,老刑警劉巖簸喂,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異燎潮,居然都是意外死亡喻鳄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門跟啤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诽表,“玉大人,你說我怎么就攤上這事隅肥「妥啵” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵腥放,是天一觀的道長泛啸。 經(jīng)常有香客問我,道長秃症,這世上最難降的妖魔是什么候址? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮种柑,結(jié)果婚禮上岗仑,老公的妹妹穿的比我還像新娘。我一直安慰自己聚请,他們只是感情好荠雕,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驶赏,像睡著了一般炸卑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上煤傍,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天盖文,我揣著相機與錄音,去河邊找鬼蚯姆。 笑死五续,一個胖子當著我的面吹牛洒敏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播返帕,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼桐玻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荆萤?” 一聲冷哼從身側(cè)響起镊靴,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎链韭,沒想到半個月后偏竟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡敞峭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年踊谋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旋讹。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡殖蚕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沉迹,到底是詐尸還是另有隱情睦疫,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布鞭呕,位于F島的核電站蛤育,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏葫松。R本人自食惡果不足惜瓦糕,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望腋么。 院中可真熱鬧咕娄,春花似錦、人聲如沸珊擂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽未玻。三九已至,卻和暖如春胡控,著一層夾襖步出監(jiān)牢的瞬間扳剿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工昼激, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庇绽,地道東北人锡搜。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像瞧掺,于是被迫代替她去往敵國和親耕餐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一壹蔓、多態(tài) 1. 概述 理解:多態(tài)可以理解為事物存在的多種體(表)現(xiàn)形態(tài)趟妥。例如:動物中的貓和狗。貓這個對象對應的是貓...
    陳凱冰閱讀 339評論 0 1
  • 寫在前面 由于找工作的原因佣蓉,最近幾個月都沒有更新博客了披摄。。勇凭。這篇可能是今年最后一篇總結(jié)類的博文了疚膊,希望能夠?qū)懙暮命c...
    niaoge2016閱讀 9,138評論 1 52
  • Java的第三大特性------>多態(tài) 一、什么是多態(tài) 多態(tài)根據(jù)其字面意思就是多種形態(tài)的意思套像,那么在Java中的多...
    hello_mr_future閱讀 621評論 0 0
  • 1.封裝 封裝的定義: 首先是抽象酿联,把事物抽象成一個類,其次才是封裝夺巩,將事物擁有的屬性和動作隱藏起來贞让,只保留特定的...
    時待吾閱讀 407評論 0 1
  • (此劇本為迎新晚會使用 作者:憨豆逗 改編者:保密 主要人物:寢室四人組:豪妹兒 ...
    瀘上芝士閱讀 754評論 0 2