Java復用、多態&接口
可以為每一個類都創建main()方法,便于單元測試
當創建一個導出類的對象時,該對象包含一個包裝在導出類對象內部的基類對象,所以java會自動的在導出類的構造器中插入對基類構造器的調用(super),在構造過程中是從基類“向外”擴散。
帶參數的構造器:
如果基類的構造器帶有參數,如Super(int i){},則導出類的構造器既可以是無參,也可以有參,如Extend() or Extend(int i),但在導出類構造器中必須用用super(int i)調用基類的構造器,否則將調用基類默認的構造器,找不到則出錯!
代理:介于繼承與組合,我們將一個成員對象置于所要構造的類中,但與此同時我們在新類中暴露了該成員對象的所有方法(就像繼承),通過代理可以選擇提供成員對象部分方法,java不直接支持代理!
向上轉型:導出類轉換成基類,實際上僅僅是堆棧中的類引用的變化,增加了一個基類引用,指向堆中的對象(導出類引用和基類引用指向同一個對象),與導出類引用相比,基類引用僅僅是少了一些借口而已,如果基類引用指向的是一個導出類對象,則向下轉型不會發生任何問題。
final 數據:常量,參數:參數引用所指向的對象無法更改,方法:鎖定,不被覆蓋,類:不被繼承
private方法被自動認為是final方法,而對導出類是屏蔽的,不可重載
“封裝”通過合并特征和行為來創建新的數據類型。“實現隱藏”則通過將細節“私有化”把接口與實現分離,多態消除類型之間的偶合關系。
方法綁定(將一個方法調用同一個方法主題關聯起來):前期綁定(通過編譯器和連接程序實現)用于面向過程的語言;后期綁定(動態、運行時綁定)在運行時根據對象的類型進行綁定,在運行是判斷對象的類型,從而調用恰當的方法。(此處說法與自己的理解稍有出入,主要是還不明白對象類方法調用機制)
構造器內部的多態方法的行為:如果在一個構造器內部調用正在構造的對象的某個動態綁定方法,例子如下:
public class Test { public static void main(String[] args) { new B(); } } class A { void func() { System.out.println("fA"); } A() { System.out.println("begin A"); func(); System.out.println("end A"); } } class B extends A { void func() { System.out.println("fB " + i); } int i = 1; B() { super(); System.out.println("B " + i); } } /*output begin A fB 0 end A B 1 */ |
(對象的初始化順序見《初始化與清理》)首先執行基類A的構造方法,再調用func()方法,由于func()方法已被導出類B覆蓋,實際上執行的是B.func(),最后再執行類B的構造方法。問題的關鍵是在A中執行B.func()時,輸出的i是0,而不是1,說明此時導出類B的成員還未初始化,這也驗證了《初始化與清理》中初始化的順序問題。所以在構造器中唯一能安全調用的方法是基類的final方法。
接口被用來建立類與類之間的協議