2017年11月4日 星期六

Day2-3 - Polymorphism 多型

5.2 Given a scenario, develop code that demonstrates the use of polymorphism. Further, determine when casting will be necessary and recognize compiler vs. runtime errors related to object reference casting. 

- 任何可以被測試通過不只一個IS-A的Java Object就是Polymorphism
- 除了Object Class的物件外,其他所有Java Object都是Polymorphism,因為他們可以通過IS-A測試。例如:PS4是一種(IS-A)PS4, PS4是一種(IS-An)Object
- 存取Object的唯一方法:使用reference variable

  • reference variable一旦宣告就不能夠更改type(但可以改變reference object裡的內容)
  • reference variable一但決定了type,就可以使用該type的method
  • reference variable可以重新assign另一個object(除非reference variable是final),但要注意的是,assign的type必須是原本object的superclass

思考以下情境:
假設現在有兩種遊戲機Class,分別是PS4 Class和Xbox Class,這兩個都是一個遊戲機器,所以他們都extends GameEntmtEquip。但今天有touchPad()的只有PS4 Class,則要如何處理繼承?以下有幾種想法:
  1. 把touchPad()寫入GameEntmtEquip Class,只讓有touchPad()的Class實作 >> 錯Wrong! 容易出錯,減少GameEntmtEquip cohesion(內聚力),也會讓其他GameEntmtEquip subClass認為有機會使用touchPad()
  2. 建立一個TouchPad的Class,在裡面寫touchPad(),並且只讓PS4 Class繼承  TouchPad Class,也就是 PS4 extends GameEntmtEquip and TouchPad | Xbox extends GameEntmtEquip >> Wrong! Java只有single inheritance,意指一個Class只能有一個immediate superclass(直接父類別),但注意可以有多個祖先
  3. 建立一個TouchPad interface,讓有touchPad()需求的Class實作此interface >> Correct!
  4. 一個reference variable可以被宣告成class type或interface type
取第三個方法,設計如下:
TouchPad interface
public interface TouchPad {
    void touchPad();
}
superClass GameEntmtEquip
public abstract class GameEntmtEquip {
    abstract void playGame();
}
XBox Class
public class XBox extends GameEntmtEquip{
    public void playGame() {...}
}
XBox Class PS4 Class實作TouchPad interface
public class PS4 extends GameEntmtEquip implements TouchPad {
    @Override    public void playGame() {  /*...*/ }
    @Override    public void touchPad() { /*...*/ }
}
現在,PS4 reference variable就是polymorphism,因為他可以通過以下任一個IS-A
  • PS4 IS-A Object (PS4 extends Object)
  • PS4 IS-A GameEntmtEquip (PS4 extends GameEntmtEquip)
  • PS4 IS-A TouchPad (PS4 implements TouchPad)
  • PS4 IS-A PS4
下面所有情況的variable reference都是正確
PS4 ps4 = new PS4();
Object o = ps4;
GameEntmtEquip ga = ps4;
TouchPad tp = ps4;
- 範例中有四個reference variable,他是ps4, o, ga, tp
- 範例中只有一個object,他是ps4- o, ga, tp, ps4都指向ps4這個object
- 不論object的type為何(ps4),編譯器只依靠reference variable的宣告type(此處為o或gatpps4)呼叫可使用的method。
- 所以上述只有ps4和ga可以呼叫playGame(),因為看的是reference variable的type
- 不論reference variable是什麼type或interface,都可以使用Object內的methods
- JVM還是知道ps4 object的真實type,所以如果GameEntmtEquip和PS4都有playGame()的程式碼,則
ga.playGame();
ps4.playGame();
兩者都會使用PS4所實作的程式碼來執行。因為JVM會去呼叫該object的真實型別看看有沒有被override,若有,就會使用。
- 注意!只有被override instance method會依照object真實型別去動態的選擇呼叫的method,static methods和variable變數都不會。
- object reference 決定了在執行時期要使用哪一個overriding method。在compile時期,由reference variable決定了要使用哪一個overloading method。
結論:polymorphism只能適用於instance method!!

沒有留言:

張貼留言