7: Polymorphism(多態(tài)性)

再訪上傳(upcasting)
把對象的類型忘掉

問題的關(guān)鍵
方法調(diào)用的綁定
當(dāng)綁定發(fā)生在程序運(yùn)行之前時(shí)(如果有的話,就是由編譯器或連接器負(fù)責(zé))被稱作“前綁定(early binding)”。
“后綁定(late binding)”的意思是要在程序運(yùn)行的時(shí)候,根據(jù)對象的類型來決定該綁定哪個(gè)方法。后綁定也被稱為“動(dòng)態(tài)綁定(dynamic)”或“運(yùn)行時(shí)綁定(run-time binding)”。
除了static和final方法(private方法隱含有final的意思),Java的所有的方法都采用后綁定。也就是說,通常情況下你不必考慮是不是應(yīng)該采用后綁定——它是自動(dòng)的。
產(chǎn)生正確的行為
可擴(kuò)展性
錯(cuò)誤:“覆寫”private的方法
只有非private的方法才能被覆寫,別用基類的private方法的名字去命名派生類的方法。

抽象類和抽象方法
如果類包含一個(gè)或多個(gè)抽象方法,那么這個(gè)類就必須被定義成abstract的。(否則編譯器就會(huì)報(bào)錯(cuò)了。)
創(chuàng)建一個(gè)不包含abstract方法的abstract類,是完全可以的。這種技巧可以用于“不必創(chuàng)建abstract的方法,但是又要禁止別人創(chuàng)建這個(gè)類的對象”的場合。

構(gòu)造函數(shù)與多態(tài)性
構(gòu)造函數(shù)不是多態(tài)的(實(shí)際上他們都是static方法,只是聲明的時(shí)候沒有直說)。
構(gòu)造函數(shù)的調(diào)用順序
復(fù)雜對象的構(gòu)造函數(shù)的調(diào)用順序:
1. 調(diào)用基類的構(gòu)造函數(shù)。這是一個(gè)遞歸過程,因此會(huì)先創(chuàng)建繼承體系的根,然后是下一級派生類,以此類推,直到最后一個(gè)繼承類的構(gòu)造函數(shù)。
2. 成員對象按照其聲明的順序進(jìn)行初始化。
3. 執(zhí)行繼承類的構(gòu)造函數(shù)的正文。
繼承與清理
對象與對象之間有可能會(huì)有依賴關(guān)系,因此清理的順序應(yīng)該與初始化的順序相反。對數(shù)據(jù)成員而言,這就是說它們的清理順序應(yīng)該與聲明的順序相反(因?yàn)閿?shù)據(jù)的初始化是按照聲明的順序進(jìn)行的)。對基類而言(它采用了C++拆構(gòu)函數(shù)的形式),你應(yīng)該先進(jìn)行派生類的清理,再進(jìn)行基類的清理。
多態(tài)方法在構(gòu)造函數(shù)中的行為
如果你在構(gòu)造函數(shù)里面調(diào)用了動(dòng)態(tài)綁定的方法,那么它會(huì)使用那個(gè)覆寫后的版本。
一個(gè)好的構(gòu)造函數(shù)應(yīng)該,“用最少的工作量把對象的狀態(tài)設(shè)置好,而且要盡可能地避免去調(diào)用方法。”構(gòu)造函數(shù)唯一能安全調(diào)用的方法,就是基類的final方法。(這一條也適合private方法,因?yàn)樗詣?dòng)就是final的。)它們不會(huì)被覆寫,因此也不會(huì)產(chǎn)生這種意外的行為。

用繼承來進(jìn)行設(shè)計(jì)
使用繼承來表示行為的不同,而用成員數(shù)據(jù)來表示不同的狀態(tài)。
純繼承與擴(kuò)展
下傳與運(yùn)行時(shí)的類型鑒別

總結(jié)

練習(xí)

「讀書筆記」Thinking in Java 3rd Edition - 8: Interfaces & Inner Classes