兩種方法可以重複運用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");
 }
 /*********************************************************
 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();
 }
 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);
 }
 public static void main(String[] args)
 {
  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 秒)。
 
 
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;
 }
 public void dilute()
 {
  append(" dilute()");
 }
 public void apply()
 {
  append(" apply()");
 }
 public void scrub()
 {
  append(" scrub()");
 }
 public void print()
 {
  System.out.println(s);
 }
 public static void main(String[] args)
 {
  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();
 }
 //add method to the interface:
 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);
 }
}
 
 
(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 Drawing extends Art
{
 Drawing()
 {
  System.out.println("Drawing constructor");
 }
};
public class Cartoon extends Drawing
{
 /*
 Cartoon ()
 {
  System.out.println("Cartoon constructor");
 }
 */
 public static void main(String[] args)
 {
  Cartoon x = new Cartoon();
 }
}
 
---------- java ----------
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 Drawing extends Art
{
 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();
 }
}
 
---------- java ----------
Art constructor : 11
Drawing constructor : 11
Cartoon constructor
Normal Termination
輸出完成 (耗費 0 秒)。
 
 
Reference : Thinking in Java
arrow
arrow
    全站熱搜

    Kalin 發表在 痞客邦 留言(0) 人氣()