JAVA特性【多態(tài)】詳解.ppt_第1頁
JAVA特性【多態(tài)】詳解.ppt_第2頁
JAVA特性【多態(tài)】詳解.ppt_第3頁
JAVA特性【多態(tài)】詳解.ppt_第4頁
JAVA特性【多態(tài)】詳解.ppt_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、多態(tài)(polymorphism),多態(tài)的運(yùn)行機(jī)制 所謂“綁定(binding)”,就是建立method call(函數(shù)調(diào)用)和method body(函數(shù)本體)的關(guān)聯(lián)。如果綁定動作發(fā)生于程序執(zhí)行前(由編譯器和連接器完成),稱為“先期綁定”。對于面向過程的語言它們沒有其他選擇,一定是先期綁定。比如C編譯器只有一種method call,就是先期綁定。(C+有先期聯(lián)編和后期聯(lián)編),當(dāng)有多態(tài)的情況時,解決方法便是所謂的后期綁定(late binding):綁定動作將在執(zhí)行期才根據(jù)對象型別而進(jìn)行。后期綁定也被稱為執(zhí)行期綁定(run-time binding)或動態(tài)綁定(dynamic binding)

2、。,Java的所有函數(shù),除了被聲明為final者,都使用后期綁定。從表面上來理解,將函數(shù)聲明為final型這樣是為了防止他人覆寫該函數(shù)。但是或許更重要的是,這么做可以“關(guān)閉”動態(tài)綁定?;蛘哒f,這么做便是告訴編譯器:動態(tài)綁定是不需要的。于是編譯器可以產(chǎn)生效率較佳的程序代碼。這樣說來,動態(tài)綁定(后期綁定)的效率不如先期綁定了。,多態(tài)(polymorphism),Example 例如動物園的飼養(yǎng)員能夠給各種各樣的動物喂食。 圖1顯示了飼養(yǎng)員Feeder、食物Food和動物Animal以及它的子類的類框圖。,多態(tài),圖1 飼養(yǎng)員Feeder、食物Food和動物Animal以及它的子類的類框圖,多態(tài),可以

3、把Feeder、Animal和Food都看成獨(dú)立的子系統(tǒng)。Feeder類的定義如下: public class Feederpublic void feed(Animal animal,Food food)animal.eat(food); 以下程序演示一個飼養(yǎng)員分別給一只狗喂肉骨頭,給一只貓喂魚。 Feeder feeder=new Feeder();Animal animal=new Dog();Food food=new Bone();feeder.feed(animal,food); animal=new Cat();food=new Fish();feeder.feed(animal

4、,food);,/給狗喂肉骨頭,/給貓喂魚,多態(tài),Java語言允許某個類型的引用變量引用子類的實(shí)例,而且可以對這個引用變量進(jìn)行類型轉(zhuǎn)換: Animal animal=new Dog();Dog dog=(Dog)animal; Creature creature=animal; 如圖2所示,如果把引用變量轉(zhuǎn)換為子類類型,稱為向下轉(zhuǎn)型,如果把引用變量轉(zhuǎn)換為父類類型,稱為向上轉(zhuǎn)型。在進(jìn)行引用變量的類型轉(zhuǎn)換時,會受到各種限制。而且在通過引用變量訪問它所引用的實(shí)例的靜態(tài)屬性、靜態(tài)方法、實(shí)例屬性、實(shí)例方法,以及從父類中繼承的方法和屬性時,Java虛擬機(jī)會采用不 同的綁定機(jī)制。,/向下轉(zhuǎn)型,把Animal

5、類型轉(zhuǎn)換為Dog類型,/向上轉(zhuǎn)型,把Animal類型轉(zhuǎn)換為 Creature類型,多態(tài),圖2 類型轉(zhuǎn)換,多態(tài),下面通過具體的例子來演示多態(tài)的各種特性。 在下面的例程中,Base父類和Sub子類中都定義了實(shí)例變量var、實(shí)例方法method()、靜態(tài)變量staticVar和靜態(tài)方法staticMethod(),此外,在Sub類中還定義了實(shí)例變量subVar和subMethod()。 Sub.javapackage poly;class BaseString var=BaseVar; static String staticVar=StaticBaseVar; void method() Syst

6、em.out.println(Base method);static void staticMethod() System.out.println(Static Base method);,/實(shí)例變量,/靜態(tài)變量,/實(shí)例方法,/靜態(tài)方法,多態(tài),public class Sub extends BaseString var=SubVar; /實(shí)例變量static String staticVar=StaticSubVar; /靜態(tài)變量 void method() /覆蓋父類的method()方法 System.out.println(Sub method);static void staticM

7、ethod() /隱藏父類的staticMethod()方法System.out.println(Static Sub method); String subVar=Var only belonging to Sub;void subMethod()System.out.println(Method only belonging to Sub);public static void main(String args)Base who=new Sub(); /who被聲明為Base類型,引用Sub實(shí)例System.out.println(who.var=+who.var); System.out

8、.println(who.staticVar=+who.staticVar); who.method(); who.staticMethod(); ,/打印Base類的var變量,/打印Base類的staticVar變量,/打印Sub實(shí)例的method()方法,/打印Base類的staticMethod()方法,多態(tài),(1)對于一個引用類型的變量,Java編譯器按照它聲明的類型來處理。 例如在以下代碼中,編譯器認(rèn)為who是Base類型的引用變量,不存在subVar成員變量和subMethod()方法,所以編譯出錯: Base whonew Sub(); /who是Base類型who.subVa

9、r=“123”; /編譯出錯,提示在Base類中沒有subVar屬性who.subMethod(); /編譯出錯,提示在Base類中沒有subMethod()方法 如果要訪問Sub類的成員,必須通過強(qiáng)制類型的轉(zhuǎn)換:Base whonew Sub(); /who是Base類型(Sub)who).subVar=123; /編譯成功,把Base引用類型強(qiáng)制轉(zhuǎn)換為Sub引用類型(Sub)who).subMethod(); /編譯成功,把Base引用類型強(qiáng)制轉(zhuǎn)換為Sub引用類型,多態(tài),Java編譯器允許具有直接或間接繼承關(guān)系的類之間進(jìn)行類型轉(zhuǎn)換. 對于向上轉(zhuǎn)型,不必使用強(qiáng)制類型轉(zhuǎn)換,因?yàn)樽宇惖膶ο罂隙ㄒ?/p>

10、可看作父類的對象。例如一個Dog對象是一個Animal對象,也是一個Creature對象,也是一個Object對象: Dog dog=new Dog();Creature creature=dog; /編譯成功,把Dog引用類型直接轉(zhuǎn)換為Creature引用類型Object object=dog; /編譯成功,把Dog引用類型直接轉(zhuǎn)換為Object引用類型 對于向下轉(zhuǎn)型,必須進(jìn)行強(qiáng)制類型轉(zhuǎn)換: Creature creature=new Cat(); Animal animal=(Animal)creature; /編譯成功,把Creature引用類型強(qiáng)制轉(zhuǎn)換為Animal引用類型Cat ca

11、t=(Cat)creature; /編譯成功,把Creature引用類型強(qiáng)制轉(zhuǎn)換為Cat引用類型Dog dog=(Dog)creature; /編譯成功,把Creature引用類型強(qiáng)制轉(zhuǎn)換為Dog引用類型,多態(tài),假如兩種類型之間沒有繼承關(guān)系,即不在繼承樹的同一個繼承分支上,那么Java編譯器不允許進(jìn)行類型轉(zhuǎn)換,例如: Dog dog=new Dog();Cat cat=(Cat)dog; /編譯出錯,不允許把Dog引用類型轉(zhuǎn)換為Cat引用類型 (2)對于一個引用類型變量,運(yùn)行時Java虛擬機(jī)按照它實(shí)際引用的對象來處理。例如以下代碼雖然編譯可以通過,但運(yùn)行時會拋出ClassCastExcepti

12、on運(yùn)行時異常: Base who=new Base(); /who引用Base類的實(shí)例Sub s=(Sub)who; /運(yùn)行時拋出ClassCastException 在運(yùn)行時,子類的對象可以轉(zhuǎn)換為父類類型,而父類的對象實(shí)際上無法轉(zhuǎn)換為子類類型。因?yàn)橥ㄋ椎闹v,父類擁有的成員子類肯定也有,而子類擁有的成員父類不一定有。,多態(tài),假定Java虛擬機(jī)能夠把子類對象轉(zhuǎn)換為父類類型,那么以下代碼中的sub.subMethod()方法無法執(zhí)行: Base who=new Base(); /who引用Base類的實(shí)例Sub sub=(Sub)who; /假定運(yùn)行時未出錯sub.subMethod(); /s

13、ub引用變量實(shí)際上引用Base實(shí)例,而Base實(shí)例沒有subMethod()方法 由此可見,在運(yùn)行時,Java虛擬機(jī)無法把子類對象轉(zhuǎn)變?yōu)楦割愵愋?。以下代碼盡管能夠編譯成功,但在運(yùn)行時,creature變量引用的Cat對象無法轉(zhuǎn)變?yōu)镈og類型,因此會拋出ClassCastException: Creature creature=new Cat(); Animal animal=(Animal)creature; /運(yùn)行正常,Cat對象可轉(zhuǎn)換為Animal類型Cat cat=(Cat)creature; /運(yùn)行正常,Cat對象可以被Cat類型的引用變量引用Dog dog=(Dog)creature

14、; /運(yùn)行時拋出ClassCastException,Cat對象不可轉(zhuǎn)換為Dog類型 (第9頁為編譯成功),多態(tài),(3)在運(yùn)行時環(huán)境中,通過引用類型變量來訪問所引用對象的方法和屬性時,Java虛擬機(jī)采用以下綁定規(guī)則: 1)實(shí)例方法與引用變量實(shí)際引用的對象的方法綁定,這種綁定屬于動態(tài)綁定,因?yàn)槭窃谶\(yùn)行時由Java虛擬機(jī)動態(tài)決定的。 2)靜態(tài)方法與引用變量所聲明的類型的方法綁定,這種綁定屬于靜態(tài)綁定,因?yàn)閷?shí)際上是在編譯階段就已經(jīng)作了綁定。 3)成員變量(包括靜態(tài)變量和實(shí)例變量)與引用變量所聲明的類型的成員變量綁定,這種綁定屬于靜態(tài)綁定,因?yàn)閷?shí)際上是在編譯階段就已經(jīng)作了綁定。,多態(tài),例如,對于以下這

15、段代碼: Base who=new Sub(); /who被聲明為Base類型,引用Sub實(shí)例System.out.println(who.var=+who.var); /打印Base類的var變量System.out.println(who.staticVar=+who.staticVar); /打印Base類的staticVar變量who.method(); /打印Sub實(shí)例的method()方法who.staticMethod(); /打印Base類的staticMethod()方法 運(yùn)行時將會輸出如下結(jié)果: who.var=BaseVarwho.staticVar=StaticBase

16、VarSub methodStatic Base method,多態(tài),再看一個例子: public abstract class Aabstract void method();void test()method(); /到底調(diào)用哪個類的mehtod()方法? public class B extends Avoid method() /覆蓋父類的method()方法System.out.println(Sub);public static void main(String args)new B().test();,多態(tài),運(yùn)行類B的main()方法將打印Sub。 方法test()在父類A中定義

17、,它調(diào)用了方法method()。雖然方法method()在類A 中被定義為是抽象的,它仍然可以被調(diào)用,因?yàn)樵谶\(yùn)行時環(huán)境中,Java虛擬機(jī)會執(zhí)行類B的實(shí)例的method()方法。一個實(shí)例所屬的類肯定實(shí)現(xiàn)了父類中 所有的抽象方法(否則這個類不能被實(shí)例化)。 再看一個例子: public class Avoid method()System.out.println(Base);void test()method(); public class B extends Avoid method()System.out.println(Sub); public static void main(String args)new A().test(); /調(diào)用類A的method()方法new B().test(); /調(diào)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論