版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Java的多態(tài)性面向?qū)ο缶幊逃腥齻€(gè)特征,即封裝、繼承和多態(tài)。 封裝隱藏了類的內(nèi)部實(shí)現(xiàn)機(jī)制,從而可以在不影響使用者的前提下改變類的內(nèi)部結(jié)構(gòu),同時(shí)保護(hù)了數(shù)據(jù)。 繼承是為了重用父類代碼,同時(shí)為實(shí)現(xiàn)多態(tài)性作準(zhǔn)備。那么什么是多態(tài)呢? 方法的重寫、重載與動(dòng)態(tài)連接構(gòu)成多態(tài)性。Java之所以引入多態(tài)的概念,原因之一是它在類的繼承問題上和C+不同,后者允許多繼承,這確實(shí)給其帶來的非常強(qiáng)大的功能,但是復(fù)雜的繼承關(guān)系也給C+開發(fā)者帶來了更大的麻煩,為了規(guī)避風(fēng)險(xiǎn),Java只允許單繼承,派生類與基類間有IS-A的關(guān)系(即“貓”is a “動(dòng)物”)。這樣做雖然保證了繼承關(guān)系的簡單明了,但是勢必在功能上有很大的限制,所以,
2、Java引入了多態(tài)性的概念以彌補(bǔ)這點(diǎn)的不足,此外,抽象類和接口也是解決單繼承規(guī)定限制的重要手段。同時(shí),多態(tài)也是面向?qū)ο缶幊痰木杷凇?要理解多態(tài)性,首先要知道什么是“向上轉(zhuǎn)型”。 我定義了一個(gè)子類Cat,它繼承了Animal類,那么后者就是前者是父類。我可以通過Cat c = new Cat();實(shí)例化一個(gè)Cat的對(duì)象,這個(gè)不難理解。但當(dāng)我這樣定義時(shí):Animal a = new Cat();這代表什么意思呢? 很簡單,它表示我定義了一個(gè)Animal類型的引用,指向新建的Cat類型的對(duì)象。由于Cat是繼承自它的父類Animal,所以Animal類型的引用是可以指向Cat類型的對(duì)象的。那么這樣
3、做有什么意義呢?因?yàn)樽宇愂菍?duì)父類的一個(gè)改進(jìn)和擴(kuò)充,所以一般子類在功能上較父類更強(qiáng)大,屬性較父類更獨(dú)特,定義一個(gè)父類類型的引用指向一個(gè)子類的對(duì)象既可以使用子類強(qiáng)大的功能,又可以抽取父類的共性。所以,父類類型的引用可以調(diào)用父類中定義的所有屬性和方法,而對(duì)于子類中定義而父類中沒有的方法,它是無可奈何的;同時(shí),父類中的一個(gè)方法只有在在父類中定義而在子類中沒有重寫的情況下,才可以被父類類型的引用調(diào)用;對(duì)于父類中定義的方法,如果子類中重寫了該方法,那么父類類型的引用將會(huì)調(diào)用子類中的這個(gè)方法,這就是動(dòng)態(tài)連接??聪旅孢@段程序:class Father public void func1() func2();
4、/這是父類中的func2()方法,因?yàn)橄旅娴淖宇愔兄貙懥嗽摲椒?/所以在父類類型的引用中調(diào)用時(shí),這個(gè)方法將不再有效 /取而代之的是將調(diào)用子類中重寫的func2()方法 public void func2() System.out.println("AAA"); class Child extends Father /func1(int i)是對(duì)func1()方法的一個(gè)重載 /由于在父類中沒有定義這個(gè)方法,所以它不能被父類類型的引用調(diào)用 /所以在下面的main方法中child.func1(68)是不對(duì)的 public void func1(int i) System.out.
5、println("BBB"); /func2()重寫了父類Father中的func2()方法 /如果父類類型的引用中調(diào)用了func2()方法,那么必然是子類中重寫的這個(gè)方法 public void func2() System.out.println("CCC"); public class PolymorphismTest public static void main(String args) Father child = new Child(); child.func1();/打印結(jié)果將會(huì)是什么? 上面的程序是個(gè)很典型的多態(tài)的例子。子類Child繼
6、承了父類Father,并重載了父類的func1()方法,重寫了父類的func2()方法。重載后的func1(int i)和func1()不再是同一個(gè)方法,由于父類中沒有func1(int i),那么,父類類型的引用child就不能調(diào)用func1(int i)方法。而子類重寫了func2()方法,那么父類類型的引用child在調(diào)用該方法時(shí)將會(huì)調(diào)用子類中重寫的func2()。 那么該程序?qū)?huì)打印出什么樣的結(jié)果呢?很顯然,應(yīng)該是“CCC”。 對(duì)于多態(tài),可以總結(jié)它為:一、使用父類類型的引用指向子類的對(duì)象; 二、該引用只能調(diào)用父類中定義的方法和變量; 三、如果子類中重寫了父類中的一個(gè)方法,那么在調(diào)用這個(gè)
7、方法的時(shí)候,將會(huì)調(diào)用子類中的這個(gè)方法;(動(dòng)態(tài)連接、動(dòng)態(tài)調(diào)用) 四、變量不能被重寫(覆蓋),”重寫“的概念只針對(duì)方法,如果在子類中”重寫“了父類中的變量,那么在編譯時(shí)會(huì)報(bào)錯(cuò)。 *多態(tài)詳解(整理)2008-09-03 19:29多態(tài)是通過: 1 接口 和 實(shí)現(xiàn)接口并覆蓋接口中同一方法的幾不同的類體現(xiàn)的 2 父類 和 繼承父類并覆蓋父類中同一方法的幾個(gè)不同子類實(shí)現(xiàn)的.一、基本概念 多態(tài)性:發(fā)送消息給某個(gè)對(duì)象,讓該對(duì)象自行決定響應(yīng)何種行為。 通過將子類對(duì)象引用賦值給超類對(duì)象引用變量來實(shí)現(xiàn)動(dòng)態(tài)方法調(diào)用。 java 的這種機(jī)制遵循一個(gè)原則:當(dāng)超類對(duì)象引用變量引用子類對(duì)象時(shí),被引用對(duì)象的類型而不是引用變量的
8、類型決定了調(diào)用誰的成員方法,但是這個(gè)被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。 1. 如果a是類A的一個(gè)引用,那么,a可以指向類A的一個(gè)實(shí)例,或者說指向類A的一個(gè)子類。 2. 如果a是接口A的一個(gè)引用,那么,a必須指向?qū)崿F(xiàn)了接口A的一個(gè)類的實(shí)例。 二、Java多態(tài)性實(shí)現(xiàn)機(jī)制 SUN目前的JVM實(shí)現(xiàn)機(jī)制,類實(shí)例的引用就是指向一個(gè)句柄(handle)的指針,這個(gè)句柄是一對(duì)指針: 一個(gè)指針指向一張表格,實(shí)際上這個(gè)表格也有兩個(gè)指針(一個(gè)指針指向一個(gè)包含了對(duì)象的方法表,另外一個(gè)指向類對(duì)象,表明該對(duì)象所屬的類型); 另一個(gè)指針指向一塊從java堆中為分配出來內(nèi)存空間。 三、總結(jié) 1、通
9、過將子類對(duì)象引用賦值給超類對(duì)象引用變量來實(shí)現(xiàn)動(dòng)態(tài)方法調(diào)用。 DerivedC c2=new DerivedC(); BaseClass a1= c2; /BaseClass 基類,DerivedC是繼承自BaseClass的子類 a1.play(); /play()在BaseClass,DerivedC中均有定義,即子類覆寫了該方法 分析: * 為什么子類的類型的對(duì)象實(shí)例可以覆給超類引用? 自動(dòng)實(shí)現(xiàn)向上轉(zhuǎn)型。通過該語句,編譯器自動(dòng)將子類實(shí)例向上移動(dòng),成為通用類型BaseClass; * a.play()將執(zhí)行子類還是父類定義的方法? 子類的。在運(yùn)行時(shí)期,將根據(jù)a這個(gè)對(duì)象引用實(shí)際的類型來獲取對(duì)應(yīng)
10、的方法。所以才有多態(tài)性。一個(gè)基類的對(duì)象引用,被賦予不同的子類對(duì)象引用,執(zhí)行該方法時(shí),將表現(xiàn)出不同的行為。 在a1=c2的時(shí)候,仍然是存在兩個(gè)句柄,a1和c2,但是a1和c2擁有同一塊數(shù)據(jù)內(nèi)存塊和不同的函數(shù)表。 2、不能把父類對(duì)象引用賦給子類對(duì)象引用變量 BaseClass a2=new BaseClass(); DerivedC c1=a2;/出錯(cuò) 在java里面,向上轉(zhuǎn)型是自動(dòng)進(jìn)行的,但是向下轉(zhuǎn)型卻不是,需要我們自己定義強(qiáng)制進(jìn)行。 c1=(DerivedC)a2; 進(jìn)行強(qiáng)制轉(zhuǎn)化,也就是向下轉(zhuǎn)型. 3、記住一個(gè)很簡單又很復(fù)雜的規(guī)則,一個(gè)類型引用只能引用引用類型自身含有的方法和變量。 你可能說這
11、個(gè)規(guī)則不對(duì)的,因?yàn)楦割愐弥赶蜃宇悓?duì)象的時(shí)候,最后執(zhí)行的是子類的方法的。 其實(shí)這并不矛盾,那是因?yàn)椴捎昧撕笃诮壎ǎ瑒?dòng)態(tài)運(yùn)行的時(shí)候又根據(jù)型別去調(diào)用了子類的方法。而假若子類的這個(gè)方法在父類中并沒有定義,則會(huì)出錯(cuò)。 例如,DerivedC類在繼承BaseClass中定義的函數(shù)外,還增加了幾個(gè)函數(shù)(例如 myFun()) 分析: 當(dāng)你使用父類引用指向子類的時(shí)候,其實(shí)jvm已經(jīng)使用了編譯器產(chǎn)生的類型信息調(diào)整轉(zhuǎn)換了。 這里你可以這樣理解,相當(dāng)于把不是父類中含有的函數(shù)從虛擬函數(shù)表中設(shè)置為不可見的。注意有可能虛擬函數(shù)表中有些函數(shù)地址由于在子類中已經(jīng)被改寫了,所以對(duì)象虛擬函數(shù)表中虛擬函數(shù)項(xiàng)目地址已經(jīng)被設(shè)置為子類
12、中完成的方法體的地址了。 4、Java與C+多態(tài)性的比較 jvm關(guān)于多態(tài)性支持解決方法是和c+中幾乎一樣的, 只是c+中編譯器很多是把類型信息和虛擬函數(shù)信息都放在一個(gè)虛擬函數(shù)表中,但是利用某種技術(shù)來區(qū)別。 Java把類型信息和函數(shù)信息分開放。Java中在繼承以后,子類會(huì)重新設(shè)置自己的虛擬函數(shù)表,這個(gè)虛擬函數(shù)表中的項(xiàng)目有由兩部分組成。從父類繼承的虛擬函數(shù)和子類自己的虛擬函數(shù)。 虛擬函數(shù)調(diào)用是經(jīng)過虛擬函數(shù)表間接調(diào)用的,所以才得以實(shí)現(xiàn)多態(tài)的。 Java的所有函數(shù),除了被聲明為final的,都是用后期綁定。四. 1個(gè)行為,不同的對(duì)象,他們具體體現(xiàn)出來的方式不一樣, 比如: 方法重載 overloadi
13、ng 以及 方法重寫(覆蓋)override class Human void run()輸出 人在跑 class Man extends Human void run()輸出 男人在跑 這個(gè)時(shí)候,同是跑,不同的對(duì)象,不一樣(這個(gè)是方法覆蓋的例子) class Test void out(String str)輸出 str void out(int i)輸出 i 這個(gè)例子是方法重載,方法名相同,參數(shù)表不同 ok,明白了這些還不夠,還用人在跑舉例 Human ahuman=new Man(); 這樣我等于實(shí)例化了一個(gè)Man的對(duì)象,并聲明了一個(gè)Human的引用,讓它去指向Man這個(gè)對(duì)象 意思是說,
14、把 Man這個(gè)對(duì)象當(dāng) Human看了. 比如去動(dòng)物園,你看見了一個(gè)動(dòng)物,不知道它是什么, "這是什么動(dòng)物? " "這是大熊貓! " 這2句話,就是最好的證明,因?yàn)椴恢浪谴笮茇?但知道它的父類是動(dòng)物,所以, 這個(gè)大熊貓對(duì)象,你把它當(dāng)成其父類 動(dòng)物看,這樣子合情合理. 這種方式下要注意 new Man();的確實(shí)例化了Man對(duì)象,所以 ahuman.run()這個(gè)方法 輸出的 是 "男人在跑 " 如果在子類 Man下你 寫了一些它獨(dú)有的方法 比如 eat(),而Human沒有這個(gè)方法, 在調(diào)用eat方法時(shí),一定要注意 強(qiáng)制類型轉(zhuǎn)換 (
15、Man)ahuman).eat(),這樣才可以. 對(duì)接口來說,情況是類似的.實(shí)例:package domatic; /定義超類superA class superA int i = 100; void fun(int j) j = i; System.out.println("This is superA"); / 定義superA的子類subB class subB extends superA int m = 1; void fun(int aa) System.out.println("This is subB"); / 定義superA的子類su
16、bC class subC extends superA int n = 1; void fun(int cc) System.out.println("This is subC"); class Test public static void main(String args) superA a = new superA(); subB b = new subB(); subC c = new subC(); a = b; a.fun(100); a = c; a.fun(200); /* 上述代碼中subB和subC是超類superA的子類,我們?cè)陬怲est中聲明了3個(gè)
17、引用變量a, b, c,通過將子類對(duì)象引用賦值給超類對(duì)象引用變量來實(shí)現(xiàn)動(dòng)態(tài)方法調(diào)用。也許有人會(huì)問: "為什么(1)和(2)不輸出:This is superA"。 * java的這種機(jī)制遵循一個(gè)原則:當(dāng)超類對(duì)象引用變量引用子類對(duì)象時(shí), * 被引用對(duì)象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法, * 但是這個(gè)被調(diào)用的方法必須是在超類中定義過的, * 也就是說被子類覆蓋的方法。 * 所以,不要被上例中(1)和(2)所迷惑,雖然寫成a.fun(),但是由于(1)中的a被b賦值, * 指向了子類subB的一個(gè)實(shí)例,因而(1)所調(diào)用的fun()實(shí)際上是子類subB的成員方法fu
18、n(), * 它覆蓋了超類superA的成員方法fun();同樣(2)調(diào)用的是子類subC的成員方法fun()。 * 另外,如果子類繼承的超類是一個(gè)抽象類,雖然抽象類不能通過new操作符實(shí)例化, * 但是可以創(chuàng)建抽象類的對(duì)象引用指向子類對(duì)象,以實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)性。具體的實(shí)現(xiàn)方法同上例。 * 不過,抽象類的子類必須覆蓋實(shí)現(xiàn)超類中的所有的抽象方法, * 否則子類必須被abstract修飾符修飾,當(dāng)然也就不能被實(shí)例化了 */ 以上大多數(shù)是以子類覆蓋父類的方法實(shí)現(xiàn)多態(tài).下面是另一種實(shí)現(xiàn)多態(tài)的方法-重寫父類方法1.JAVA里沒有多繼承,一個(gè)類之能有一個(gè)父類。而繼承的表現(xiàn)就是多態(tài)。一個(gè)父類可以有多個(gè)子類,而在子類里可以重寫父類的方法(例如方法print()),這樣每個(gè)子類里重寫的代碼不一樣,自然表現(xiàn)形式就不一樣。這樣用父類的變量去引用不同的子類,在調(diào)用這個(gè)相同的方法print()的時(shí)候得到的結(jié)果和表現(xiàn)形式就不一樣了,這就是多態(tài),相同的消息(也就是調(diào)用相同的方法)會(huì)有不同的結(jié)果。舉例說明: /父類 public cla
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 道路景觀設(shè)施承諾書
- 煙草產(chǎn)品收款流程
- 印刷廠門窗施工合同協(xié)議書
- 健身房墻面裝修合同協(xié)議
- 可持續(xù)發(fā)展成品油市場管理辦法
- 基坑降水施工合同:文物保護(hù)工程
- 廣告公司合同管理方案
- 建筑公司工程車輛司機(jī)聘用合同
- 通信設(shè)備維護(hù)服務(wù)合同
- 流行病的特征
- 馬克思主義基本原理全套課件
- 動(dòng)物生產(chǎn)新技術(shù)與應(yīng)用課件
- 三年級(jí)上冊(cè)道德與法治教案-《平安出行》 部編版
- 植物營養(yǎng)學(xué)課件:植物的鈣鎂硫營養(yǎng)
- 小學(xué)英語工作室個(gè)人年度總結(jié)5篇
- 呼市回民區(qū)萬達(dá)廣場強(qiáng)條紅線黃線專項(xiàng)培訓(xùn)考試
- 電力二次系統(tǒng)安全監(jiān)控日志規(guī)范
- 迎檢工作注意事項(xiàng)
- 二進(jìn)制與十進(jìn)制的互換課件
- 干細(xì)胞精品課件
- 點(diǎn)直線與圓的位置關(guān)系說課稿 完整版課件
評(píng)論
0/150
提交評(píng)論