兩種方法可以重複運用Classes:
1. composition(複合): 在新的Class中產生既有的Class物件, 這種情形只是單純的重複運用既有程式碼的功能, 而非重複運用其形式.
2. inheritance(繼承): 讓新的Class成為既有Class的一類, 可以實際接收既有Class的形式, 並加入新碼.
Composition: 只要將object references 置於新的classes即是.
"vm不會為每個reference產生預設物件"是有意義的, 因為這麼做會在許多情況下造成不必要的負擔, 但是如果希望初始化這些references, 可以在3個地點進行:
1. 物件定義處. 這表示它們一定能在"constructor被呼叫前完成初始化動作".
2. 在constructor裡.
3. 在實際需要用到該物件的地方. 這種方式被稱為lazy initialization(緩式初始化), 這種做法可以降低額外負擔.
以下程式用了這三種作法:
//Constructor initialization with Composition
class Soap
{
private String s;
Soap()
{
System.out.println("Soap()");
s = new String("Constructed");
}
{
private String s;
Soap()
{
System.out.println("Soap()");
s = new String("Constructed");
}
/*********************************************************
if declaring with this way: String toString(), it can't compile via vm
toString() in Soap cannot override toString() in java.lang.Object;
attempting to assign weaker access privileges; was public String toString()
*********************************************************/
public String toString()
{
return s;
}
};
if declaring with this way: String toString(), it can't compile via vm
toString() in Soap cannot override toString() in java.lang.Object;
attempting to assign weaker access privileges; was public String toString()
*********************************************************/
public String toString()
{
return s;
}
};
public class Bath
{
//Initializing at point of definition:
private String
s1 = new String("Happy"),
s2 = "Happy",
s3,
s4;
Soap castille;
int i;
float toy;
Bath()
{
System.out.println("Inside Bath()");
//intialization with constructor
s3 = new String("Joy");
i = 47;
toy = 3.14f;
castille = new Soap();
}
{
System.out.println("Inside Bath()");
//intialization with constructor
s3 = new String("Joy");
i = 47;
toy = 3.14f;
castille = new Soap();
}
void print()
{
//Delayed Initialization:
if (s4 == null)
{
s4 = new String("Joy");
}
System.out.println("s1 = "+s1);
System.out.println("s2 = "+s2);
System.out.println("s3 = "+s3);
System.out.println("s4 = "+s4);
System.out.println("i = "+i);
System.out.println("toy = "+toy);
System.out.println("castille = "+castille);
}
{
//Delayed Initialization:
if (s4 == null)
{
s4 = new String("Joy");
}
System.out.println("s1 = "+s1);
System.out.println("s2 = "+s2);
System.out.println("s3 = "+s3);
System.out.println("s4 = "+s4);
System.out.println("i = "+i);
System.out.println("toy = "+toy);
System.out.println("castille = "+castille);
}
public static void main(String[] args)
{
Bath b = new Bath();
b.print();
}
}
{
Bath b = new Bath();
b.print();
}
}
---------- java ----------
Inside Bath()
Soap()
s1 = Happy
s2 = Happy
s3 = Joy
s4 = Joy
i = 47
toy = 3.14
castille = Constructed
Normal Termination
輸出完成 (耗費 0 秒)。
Inside Bath()
Soap()
s1 = Happy
s2 = Happy
s3 = Joy
s4 = Joy
i = 47
toy = 3.14
castille = Constructed
Normal Termination
輸出完成 (耗費 0 秒)。
Inheritance:
1. 繼承後, derived class 自動獲取了base class 的所有資料成員與成員函式.
2. 為了繼承著想, base class 一般原則是將所有資料成員宣告成private, 將所有函式成員宣告為public.
3. 實施繼承時, 不一定非得使用base class 函式不可, 也可將新的method 加置derived class.
4. 即使沒有明確指出要繼承某個class, 仍會繼承Java 標準根源類別Object.
//Inheritance syntax & properties
class Cleanser
{
private String s = new String("Cleanser");
public void append(String a)
{
s += a;
}
class Cleanser
{
private String s = new String("Cleanser");
public void append(String a)
{
s += a;
}
public void dilute()
{
append(" dilute()");
}
{
append(" dilute()");
}
public void apply()
{
append(" apply()");
}
{
append(" apply()");
}
public void scrub()
{
append(" scrub()");
}
{
append(" scrub()");
}
public void print()
{
System.out.println(s);
}
{
System.out.println(s);
}
public static void main(String[] args)
{
Cleanser x = new Cleanser();
x.dilute();
x.apply();
x.scrub();
x.print();
}
};
{
Cleanser x = new Cleanser();
x.dilute();
x.apply();
x.scrub();
x.print();
}
};
public class Detergent extends Cleanser
{
//change a method:
public void scrub()
{
append(" Detergent.scrub()");
//call bass-class version:
super.scrub();
}
{
//change a method:
public void scrub()
{
append(" Detergent.scrub()");
//call bass-class version:
super.scrub();
}
//add method to the interface:
public void foam()
{
append(" foam()");
}
public void foam()
{
append(" foam()");
}
//test the new class:
public static void main(String[] args)
{
Detergent x = new Detergent();
x.dilute();
x.apply();
x.scrub();
x.foam();
x.print();
System.out.println("Testing base class");
Cleanser.main(args);
}
}
public static void main(String[] args)
{
Detergent x = new Detergent();
x.dilute();
x.apply();
x.scrub();
x.foam();
x.print();
System.out.println("Testing base class");
Cleanser.main(args);
}
}
(Kalin's 讀後心得1)
cleanser (n) 清潔工(跟每天叫我起床的cleaner一樣
); 清潔劑(在這篇紀錄裡面應該是指清潔劑)

di'lute (v) 稀釋; 沖淡; 減輕 (a)沖淡的; 褪了色的
scrub (v) 擦洗
de'terge (v) 洗淨
det'ergent (n) 清潔劑 (a)有清淨力的
foam (v) 起泡沫 (n)泡沫
base class 的初始化: 建構動作會由base class"往外"擴散, 所以base class會在derived class 建構式取用它之前, 先完成本身的初始化動作.
//Constructor calls during inheritance
class Art
{
Art()
{
System.out.println("Art constructor");
}
};
class Art
{
Art()
{
System.out.println("Art constructor");
}
};
class Drawing extends Art
{
Drawing()
{
System.out.println("Drawing constructor");
}
};
{
Drawing()
{
System.out.println("Drawing constructor");
}
};
public class Cartoon extends Drawing
{
/*
Cartoon ()
{
System.out.println("Cartoon constructor");
}
*/
{
/*
Cartoon ()
{
System.out.println("Cartoon constructor");
}
*/
public static void main(String[] args)
{
Cartoon x = new Cartoon();
}
}
{
Cartoon x = new Cartoon();
}
}
---------- java ----------
Art constructor
Drawing constructor
Normal Termination
輸出完成 (耗費 0 秒)。
Art constructor
Drawing constructor
Normal Termination
輸出完成 (耗費 0 秒)。
由執行class Cartoon 的結果看來, 即使並未撰寫Cartoon()建構式, vm也會為我們合成一個default 建構式, 並在其中呼叫base class 的建構式.
帶有引數(arguments)的建構式: 如果base class不具備default建構式, 或者想呼叫帶有引數的base calss constructor, 便得運用關鍵字super, 並搭配適當的引數列. 而且必須是derived class建構式的第一件要做的事情, 否則vm會提醒錯誤發生: call to super must be first statement in constructor.
//Constructor calls during inheritance
class Art
{
Art(int i)
{
System.out.println("Art constructor : "+i);
}
};
class Art
{
Art(int i)
{
System.out.println("Art constructor : "+i);
}
};
class Drawing extends Art
{
Drawing(int i)
{
super(i);
/**********************************************
假如沒有super(i), 編譯時會出現一個錯誤:
Art(int) in Art cannot be applied to ()
**********************************************/
System.out.println("Drawing constructor : "+i);
}
};
{
Drawing(int i)
{
super(i);
/**********************************************
假如沒有super(i), 編譯時會出現一個錯誤:
Art(int) in Art cannot be applied to ()
**********************************************/
System.out.println("Drawing constructor : "+i);
}
};
public class Cartoon extends Drawing
{
Cartoon ()
{
super(11);
/**********************************************
假如沒有super(1), 編譯時會出現一個錯誤:
Cartoon.java:23: cannot resolve symbol
symbol : constructor Drawing ()
**********************************************/
System.out.println("Cartoon constructor");
}
public static void main(String[] args)
{
Cartoon x = new Cartoon();
}
}
{
Cartoon ()
{
super(11);
/**********************************************
假如沒有super(1), 編譯時會出現一個錯誤:
Cartoon.java:23: cannot resolve symbol
symbol : constructor Drawing ()
**********************************************/
System.out.println("Cartoon constructor");
}
public static void main(String[] args)
{
Cartoon x = new Cartoon();
}
}
---------- java ----------
Art constructor : 11
Drawing constructor : 11
Cartoon constructor
Normal Termination
輸出完成 (耗費 0 秒)。
Art constructor : 11
Drawing constructor : 11
Cartoon constructor
Normal Termination
輸出完成 (耗費 0 秒)。
Reference : Thinking in Java
全站熱搜