天天看點

《JAVA程式設計思想》第四版學習 需要我記住的something--多态

一. 面向對象程式設計三個基本特性:資料抽象(data abstraction)、繼承(inheritance)和多态(polymorphism)。

二.通過分離"做什麼"和"怎麼做",多态從另一個角度将接口與實作分離開。

      多态不但能夠改善代碼組織結構和可讀性,而且可以建立"可擴充"(extensible)的代碼(無論是在項目最初建立時,還是在需要添加新功能時,都可以進行擴充)。

      多态-消除類型(types)之間的耦合關系(多個繼承自同一基類的類都可以當做一種類型-基類來看待)。

      多态、動态綁定(dynamic binding)、後綁定(late binding)、運作時綁定(run-time binding)。

三. 多态使程式更簡潔,可擴充。不使用向上轉型和多态,而采用重載的方式實作,那在擴充繼承類的時候,将有大量的工作要做(如添加以新增類為參數的方法代碼)。是以,忘記對象類型吧(該忘記的時候)。

多态使你的代碼變動不會破壞程式中不應受影響的其它部分,換句話說,多态是一項"将變化的事情與不變的事情分離開"的重要技術。

四.綁定(binding):将一個方法調用同方法實體連結起來;

      前綁定(early binding):綁定發生在程式運作之前(編譯器、連結器完成);

      後綁定(late binding)、動态綁定、運作時綁定:在程式運作時,根據對象的具體類型進行綁定。需要某種機制在運作時确定對象具體類型,并調用對應方法。是以,對象中需要存儲關于類型的資訊。

     Java中除了static或final方法(private方法隐式final)外,都是後綁定。

      final方法,禁止override;關掉後綁定,提高效率。但應隻從設計角度出發考慮final,而不應從效率的角度出發,因為大多數情況下,final方法并不能提高程式整體性能,尤其是在後來的JVM中(采用HotSpot技術)。

五.可擴充性:好的OOP程式,絕大多數或者全部方法應該隻與基類接口打交道,這樣的程式就是"可擴充"(extensible)的。

六.錯誤:重寫private方法。 private自動是final,是以不可重寫,繼承類中與基類private方法簽名相同的方法隻是個全新的method;由于private方法在繼承類中不可見,是以也不會是重載。

七.直接通路field和static方法都不是多态的,均為在編譯期解析綁定。super.field,在繼承類中通路基類field。

八.構造器不具備多态性,因為隐式static。

九.繼承類的析構應在基類之前,因為繼承類的析構可能需要調用基類的方法,需要保證基類對象存活。

十.當多個對象共享一個成員對象時,需要謹慎對待dispose,需要采用引用計數的方法(reference counting)來跟蹤通路共享對象的對象數,在共享對象的dispose中判斷refCount==0再進行真正的清理。

十一. 在構造器中調用多态方法必須小心,因為繼承類的成員尚未初始化完,此時産生的結果可能并不是所需,導緻程式bug(C++在這方面表現得更合理)。是以,構造器編寫原則:盡可能簡單的使對象進入正常狀态,如果有可能,不要調用類中其它方法(唯一能安全調用的是final方法(private也是final))。

十二. 對象自動初始化(清零,binary zero)發生在其它初始化之前(static初始化呢?)。

十三. Java SE5之後,添加了協變傳回類型(covariant return types),即繼承類的重寫方法可以傳回基類對應方法傳回類型的子類(不能是父類,可以試着考慮upcast之後對該方法的調用,如果是父類就可能出問題)。

十四. 盡管多态如此強大,設計時仍應先考慮使用組合而不是繼承,尤其是在不明确該用哪個時。組合更靈活,可以動态選擇類和相應的行為;而繼承需要在編譯器知道确切類型。參見例Transmogrify。

      解釋一下:使用組合,可以在運作時賦給所包含對象引用不同值(如不同繼承類對象的引用,state pattern);而繼承必須在編譯時就确定基類,不能運作時再繼承自不同類。

      原則:使用繼承實作行為上的差異,用fields表現狀态上的變化。(組合不正是把其它類型對象作為自己的fields麼?)

十五. Substitution & Extension

      pure substitution:不需要知道繼承類的更多資訊,甚至不需要知道對象的确切類型,隻需upcast,多态完成一切。但有時,extension才是解決特定問題的完美方案。

十六. downcasting & runtime type information (RTTI)

      upcasting永遠安全,downcasting則不然。

      Java,所有cast都被檢驗(是以可以隻通過cast操作符()來實作,而C++需要執行特殊操作獲得type-safe cast)。運作時類型識别runtime type identification (RTTI),出錯抛出ClassCastException(似乎不需要為該異常寫處理代碼,因為它更多時候訓示的是程式員的錯誤,除非特殊需要)。

      RTTI當然不隻是用來對付cast,例如你還可以通過它來擷取所處理對象的确切類型。

十七. 習題發現,finalize()方法是可以直接調用的(SE6測試)。