ThinkInJava學習筆記--4 組合、繼承與代理

《複用類》

組合:

  • 實現方法爲通過在類中添加其他類對象爲域達到目的,可以調用該類對外暴露的方法和域。
  • 通過添加類對象,即使類未申明爲public(繼承或包訪問權限),也可以通過類對象調用其public成員方法和域。

 

繼承:

  • 通過extends關鍵字得到基類向下暴露的方法和域(通常設計技巧將域設置爲private,而將方法全部設置爲public)
  • 當基類沒有默認的無參數構造器時,在導出類的構造器的第一行顯示的用super和正確的參數,調用基類構造器爲基類初始化
  • 初始化順序從基類開始,由內而外,初始化結果是:基類子對象包裝與導出類對象
  • 使用繼承同樣會導致基類所有的方法和域都被導出類獲取到,所以還可以使用代理,代理是組合與繼承的中庸選擇
  • 導出類可以直接獲取基類的方法,也可以通過重寫修改父類的方法,關鍵是導出類還能對基類方法進行重載

代理:

  • java沒有顯式的支持代理,需要手動構造相關代碼
  • 個人理解的代理是:通過組合的方式實現繼承的功能

代理實現示例:

public class TEST2 {
    private C c = new C();
    public static void main(String[] args){
        TEST2 test2 = new TEST2();
        test2.fun1();
        test2.fun2();
        test2.fun3();
    }
    public void fun1(){
        c.fun1();
    }
    public void fun2(){
        c.fun2();
    }
    public void fun3(){
        c.fun3();
    }
}
class C{
    public void fun1(){
        System.out.println("C1");
    }
    public void fun2(){
        System.out.println("C2");
    }
    public void fun3(){
        System.out.println("C3");
    }
}

對比繼承與代理:

  1. 繼承與代理都需要進行初始化:代理通過直接實例化該對象達到目的,繼承通過super關鍵字初始化一個基類子對象
  2. 繼承由java自動支持,可以減少大量的編碼;java未支持代理,但是代理可以進行更加靈活的控制;

組合與繼承的選擇:

引用書中的描述:老鷹屬於鳥的一種,所以老鷹類是基類鳥類的導出類;而老鷹由翅膀、爪子、鷹頭等等部位組成,而老鷹的頭由眼睛、耳朵等等部位組成。繼承是從通用到特殊化,組成是從多個組件到整體。

(導出類)向上轉型:

  • 可以理解爲:導出類對象可以當作基類對象進行引用,因爲導出類通過繼承基類得到(並且會用super關鍵字對基類進行初始化)了它所有的方法和域,所以可以發送給基類對象的消息同樣可以發送給導出類對象,反之,基類對象則不能當作導出類對象使用,因爲導出類是基類的特例。
public class Ying extends Birds {
    protected String foot;
    
    public static void main(String[] args){
        Ying ying = new Ying("foot num is 2","eyes num 2","chibang num 2","mouth num 1");
        Birds bird = new Birds("eyes * 2","mouth * 1","chibang * 2");
        Birds.fly(ying);
        Birds.fly(bird);
        Ying.fly(ying);
        Ying.fly(bird);
        Ying.run(ying);
    }
    public Ying(String foot, String eyes, String chibang, String mouth){
        super(eyes,mouth,chibang);
        this.foot = foot;
    }
    public static void run(Ying ying){
        UTIL.println("run with "+ying.foot);
    }
}
class Bird {
    protected String eyes;
    protected String mouth;
    protected String chibang;
    public Bird(String eyes,String mouth,String chibang){
        this.eyes = eyes;
        this.mouth = mouth;
        this.chibang = chibang;
    }
    public static void fly(Birds bird){
        UTIL.println("fly with "+ bird.chibang);
    }
}

final

final+static修飾的爲編譯期常量,定義時必須進行初始化,不能用Random.nextInt(N)進行賦值,即一經編譯,無法更改;

未使用static修飾即代表可以進行"空白"聲明,但是使用前一定要進行初始化(必須保證它在沒個構造器中被初始化),但這之後就不能再對它進行修改;

final修飾的對象引用表示的意思是:它不能再指向其它的對象的引用,但是當前指向的對象的引用是可以修改的。

final 方法:禁止被重寫;

final類:禁止被繼承,並且它所有的方法默認爲final,對該類的域則無影響。

初始化與類的加載:java語言中,每個類被編譯到各自單獨的文件中,當初次使用時(定義第一個對象,調用static內容)加載類,同時對static內容進行初始化。static是屬於類的而非對象,所以只需要初始化一次。

繼承與初始化

執行順序:自最內層的基類開始,到繼承樹底端的導出類:1.static域初始化,2.類的域賦初值(定義時給定的值,如果沒就給默認值),然後執行類的構造器。(1跟2一共兩輪,2中的兩個操作在一輪中完成)。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章