2017年11月3日 星期五

Day2-2 - Extend 繼承, IS-A, HAS-A

5.1 Develop code that implements "is-a" and/or "has-a" relationships.

- Extends everywhere.
- 即使寫一支最小的程式,也會需要用到extends

TestEql te1 = new TestEql();
TestEql te2 = new TestEql();
if (!te1.equals(te2)) //此處用到equals
  System.out.println("They are not equal")
if (te1 instanceof Object) //此處用到instanceof
  System.out.println("te1 is an Object")
輸出結果:
They are not equal
te1 is an Object
- 所有的class都會自動extends Object class
- 自然所有class都會擁有Object的method (equals, clone...)
- 可以透過extends達成以下目的

  1. 加強code reuse
  2. 使用polymorphism
code reuse
superclass寫過的method可以直接使用,不需要在subclass在重寫一次。(ex: equal)

polymorphism

public class Bicycle{
   public void printDescription() {
    System.out.println("Bike's subclass");
   }
}
public class MountainBike extends Bicycle{
  private suspension;
  public String getSuspension(){
      return this.suspension;
   }
}
public class RoadBike extends Bicycle{
  private tireWidth;
  public int getTireWidth(){
      return this.tireWidth;
   }
}
public class TestBikes {
  public static void main(String[] args){

    MountainBike mb = new MountainBike();
    RoadBike rb = new RoadBike();

    mb.getDescription();
    rb.getDescription();
  }
 public static void getDescription(Bicycle bk){
    bk.printDescription();
 }
}
輸出結果:
Bike's subclass
Bike's subclass
原因:polymorphism的美妙之處在於可以把所有Bicycle的subclass當成Bicycle,並且擁有Bicycle的method可以使用。(只要是extends Bicycle就知道一定有printDescription()可以使用)
- 注意getDescription()只宣告argument為Bicycle,但可以接受所有Bicycle的subClass
- 不需要考慮呼叫getDescription()真實型態為何,只知道他是Bicycle的subClass
- 在getDescription()內只能使用argument type的method(此例為Bicycle),而不能使用getTireWidth(),就算傳進來的Class真的是RoadBike type

IS-A
舉例:PS4是一種(Is-a)遊戲機(GameEquip)
遊戲機(GameEquip)是一種(Is-a)娛樂器材(EntmtEquip)
PS4 ---> 遊戲機 ---->娛樂器材 
public class EntmtEquip {...};
public class GameEquip extends EntmtEquip {...};
public class PS4 extends GameEquip {...};
可以說:
  • PS4 derived(衍伸) from EntmtEquip
  • PS4 同時是GameEquip和EntmtEquip的subtype
  • GameEquip extends from (Is-a) EntmtEquip
  • PS4 extends from GameEquip and EntmtEquip
HAS-A
舉例:PS4有手把(Handle),換句話說,PS4 Class擁有Handle的Reference,讓PS4可以使用這個Reference去呼叫Handle的method或 instance variable,而不需要Handle的程式碼。
- Class功能越專一,能夠減少更多Bugs
- 假如直接在PS4 Class放入Handle code,則卡車,輪椅等需要量Handle的Class都要放一份重複的程式碼。藉由將Handle製成一獨立的Class才有機會讓他能夠在其他Class被使用。

public class PS4 extends GameEntmtEquip {
  private Handle gameHandle = new Handle();//PS4 has a Handle
  public void turnRight(){
    gameHandle.turnRight();//delegate給Handle class實作
  }
};
public class Handle {
  public void turnRight(){
    //真正執行turnRight的程式碼
  }
};
- 上述範例中,PS4若要執行turnRight,將會delegate(委派)給Handle Class執行,因為Handle Class已經實作Handle所需功能,如此可避免重複程式碼
- PS4 Class隱藏實作細節
- 呼叫Handle的其他使用者並不需要知道也不需擔心turnRight真正是由誰實作,如何實作。
- 對呼叫者而言,就像是PS4 class自己在實作,甚至不知道有一個叫做Handle的class。

沒有留言:

張貼留言