7: Polymorphism(多態性)

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

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

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

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

用繼承來進行設計
使用繼承來表示行為的不同,而用成員數據來表示不同的狀態。
純繼承與擴展
下傳與運行時的類型鑒別

總結

練習

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