您好,登錄后才能下訂單哦!
一.什么是多態(tài)?
1.多態(tài)的定義
指允許不同類的對(duì)象對(duì)同一消息做出響應(yīng)。即同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式(發(fā)送消息就是函數(shù)調(diào)用)
2.多態(tài)的作用
消除類型之間的耦合關(guān)系
3.多態(tài)的說明
近代網(wǎng)絡(luò)小說泛濫,我們可以用它來舉一個(gè)例子
某日你看見你手機(jī)上有多部小說同時(shí)更新了,比如有大主宰,雪鷹領(lǐng)主,龍王傳說…在這里我們可以描述成如下:
小說a=大主宰
小說b=雪鷹領(lǐng)主
小說c=龍王傳說
…
這里所表現(xiàn)的就是多態(tài),大主宰,雪鷹領(lǐng)主,龍王傳說都是小說的子類,我們僅僅可以通過小說這個(gè)父類就能夠引用不同的子類,這就是多態(tài)–我們只有在運(yùn)行的時(shí)候才會(huì)知道引用變量所指向的具體實(shí)例對(duì)象
當(dāng)然,這樣的理解是是遠(yuǎn)遠(yuǎn)不夠的,要對(duì)多態(tài)的理解入門就必須要明白是”向上轉(zhuǎn)型”
在上面的例子中,小說(XS)是父類,大主宰(DZZ),雪鷹領(lǐng)主(XYLZ),龍王傳說(LWCS)都是其子類 于是,我們定義如下代碼
DZZ a=new DZZ();
對(duì)于這段代碼應(yīng)該都不會(huì)感覺到陌生,無非就是實(shí)例化了一個(gè)大主宰的對(duì)象 那么對(duì)于如下的這段代碼呢?
XS a=new DZZ();
在這里我們這樣理解,這里定義了一個(gè)XS類型的a,讓它指向了DZZ對(duì)象實(shí)例。由于DZZ是繼承于XS,所以DZZ可以自動(dòng)向上轉(zhuǎn)型為XS,所以a可以指向DZZ實(shí)例對(duì)象的。這樣做存在一個(gè)非常大的好處,在繼承中我們知道子類是父類的擴(kuò)展,它可以提供比父類更加強(qiáng)大的功能,如果我們定義了一個(gè)指向子類的父類引用類型,那么它除了能夠引用父類的共性外,還可以使用子類強(qiáng)大的功能
但是向上轉(zhuǎn)型也存在一些缺憾,那就是它必定會(huì)導(dǎo)致一些方法和屬性的丟失,而導(dǎo)致我們不能夠獲取它們。所以父類類型的運(yùn)用可以調(diào)用父類中定義的所有屬性和方法,對(duì)于只存在與子類中的方法和屬性它就望塵莫及了
public class XS { public void fun1() { System.out.println("XS中的fun1"); fun2(); } public void fun2() { System.out.println("XS中的fun2"); } }
public class DZZ extends XS{ /* * 子類重載父類方法 * 父類中不存在該方法,向上轉(zhuǎn)型后,父類是不能引用該方法的 */ public void fun1(String a) { System.out.println("DZZ中的fun1"); fun2(); } /* * 子類重寫父類方法 * 調(diào)用必定使用這個(gè)方法 */ public void fun2() { System.out.println("DZZ中的fun2"); } }
public class DuoTaiTest { public static void main(String[] args) { XS a=new DZZ(); a.fun1(); } } output: XS中的fun1 DZZ中的fun2
所以對(duì)于多態(tài)我們可以總結(jié)如下:
指向子類的父類引用由于向上轉(zhuǎn)型了,它只能訪問父類中擁有的方法和屬性,而對(duì)于子類中存在而父類中不存在的方法,該引用是不能使用的,盡管是重載該方法。若子類重寫了父類中的某些方法,在調(diào)用該些方法的時(shí)候,必定是使用子類中定義的這些方法(動(dòng)態(tài)連接,動(dòng)態(tài)調(diào)用)
對(duì)于面向?qū)ο?多態(tài)分為編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài),其中編輯時(shí)多態(tài)是靜態(tài)的,主要是指方法的重載,它是根據(jù)參數(shù)列表的不同來區(qū)分不同的函數(shù),通過編輯之后會(huì)變成兩個(gè)不同的函數(shù),在運(yùn)行時(shí)談不上多態(tài)。而運(yùn)行時(shí)多態(tài)是動(dòng)態(tài)的,它是通過動(dòng)態(tài)綁定來實(shí)現(xiàn)的,也就是我們所說的多態(tài)性。
二.多態(tài)的實(shí)現(xiàn)
1.實(shí)現(xiàn)條件
在剛剛開始就剃刀了繼承在為多態(tài)的實(shí)現(xiàn)做了準(zhǔn)備。子類Child繼承父類Father,我們可以編寫一個(gè)指向子類的父類類型引用,該引用既可以處理父類Father對(duì)象,也可以處理子類Child對(duì)象,當(dāng)相同的消息發(fā)送給子類或者父類對(duì)象時(shí),該對(duì)象就會(huì)根據(jù)自己所屬的引用而執(zhí)行不同的行為,這就是多態(tài)。即多態(tài)性就是相同的消息使得不同的類做出不同的響應(yīng)
Java
實(shí)現(xiàn)多態(tài)有三個(gè)必要條件:繼承,重寫,向上轉(zhuǎn)型
繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類
重寫:子類對(duì)父類中某些方法進(jìn)行重新定義,在調(diào)用這些方法時(shí)就會(huì)調(diào)用子類的方法
向上轉(zhuǎn)型:在多態(tài)中需要將子類的引用賦給父類對(duì)象,只有這樣該引用才能夠具備技能調(diào)用父類的方法和子類的方法
只有滿足了上述三個(gè)條件,我們才能夠在同一個(gè)繼承結(jié)構(gòu)中使用同一的邏輯實(shí)現(xiàn)代碼處理不同的對(duì)象,從而達(dá)到執(zhí)行不同的行為
對(duì)于Java而言,它多態(tài)的實(shí)現(xiàn)機(jī)制遵循一個(gè)原則:當(dāng)超類對(duì)象引用變量引用子類對(duì)象時(shí),被引用對(duì)象的類型而不是引用變量的類型決定了調(diào)用誰(shuí)的成員方法,但是這個(gè)被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法
2.實(shí)現(xiàn)形式
繼承
public class XS { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public XS() { } public String drink() { return "你看的小說名字:"+getName(); } public String toString() { return null; } } public class DZZ extends XS{ public DZZ() { setName("DZZ"); } public String drink() { return "你看的小說名字:"+getName(); } public String toString() { return "小說名:"+getName(); } } public class XYLZ extends XS{ /** * */ public XYLZ() { setName("XYLZ"); } public String drink() { return "你看的小說名字:"+getName(); } public String toString() { return "小說名:"+getName(); } } public class DuoTaiTest { public static void main(String[] args) { XS [] xs=new XS[2]; DZZ a=new DZZ(); XYLZ b=new XYLZ(); xs[0]=a; xs[1]=b; for(int i=0;i<2;i++) { System.out.println(xs[i].toString()+"::::"+xs[i].drink()); } System.out.println("-------------------"); } } ouput: 小說名:DZZ::::你看的小說名字:DZZ 小說名:XYLZ::::你看的小說名字:XYLZ -------------------
在上面的代碼中DZZ,XYLZ繼承XS 并且重寫了drink(),toString()方法,程序運(yùn)行結(jié)果是調(diào)用子類中方法,輸出DZZ,XYLZ的名稱,這就是多態(tài)的表現(xiàn)。不同的對(duì)象可以執(zhí)行相同的行為,但是他們都需要通過自己的實(shí)現(xiàn)方式來執(zhí)行,這就要得益于向上轉(zhuǎn)型了
我們都知道所有的類都繼承自超類Object,toString()方法也是Object中方法,當(dāng)我們這樣寫時(shí):
Object o = new DZZ(); System.out.println(o.toString()); output: 小說名:DZZ
Object,XS,DZZ三者繼承鏈關(guān)系是:DZZ—>XS—>Object。所以我們可以這樣說:當(dāng)子類重寫父類的方法被調(diào)用時(shí),只有對(duì)象繼承鏈中的最末端的方法才會(huì)被調(diào)用。但是注意如果這樣寫:
Object o = new xs(); System.out.println(o.toString()); output: null//因?yàn)镈ZZ并不存在于該對(duì)象繼承鏈中
所以基于繼承實(shí)現(xiàn)的多態(tài)可以總結(jié)如下:對(duì)于引用子類的父類類型,在處理該引用時(shí),它適用于繼承該父類的所有子類,子類對(duì)象的不同,對(duì)方法的實(shí)現(xiàn)也就不同,執(zhí)行相同動(dòng)作產(chǎn)生的行為也就不同。
如果父類是抽象類,那么子類必須要實(shí)現(xiàn)父類中所有的抽象方法,這樣該父類所有的子類一定存在統(tǒng)一的對(duì)外接口,但其內(nèi)部的具體實(shí)現(xiàn)可以各異。這樣我們就可以使用頂層類提供的統(tǒng)一接口來處理該層次的方法。
本篇文章的內(nèi)容希望能給需要的朋友一些幫助
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。