《複用類》
組合:
- 實現方法爲通過在類中添加其他類對象爲域達到目的,可以調用該類對外暴露的方法和域。
- 通過添加類對象,即使類未申明爲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");
}
}
對比繼承與代理:
- 繼承與代理都需要進行初始化:代理通過直接實例化該對象達到目的,繼承通過super關鍵字初始化一個基類子對象
- 繼承由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中的兩個操作在一輪中完成)。