Java初探:向上轉型(Upcasting)與向下轉型(Downcasting)

在之前多型(Polymorphism)的範例中,我們用到的技巧其實就是向上轉型,因此這一篇我們來討論向上轉型(Upcasting)與向下轉型(Downcasting)的差異與使用方式。在討論向上或向下轉型前,我們要先確認一下「is a」、「has a」的觀念。

「is a」的觀念

//A.java
public class A
{
  public String cName;
}

//B.java
public class B extends A
{
  public String cAddress;
}

//C.java
public class C
{
  public static void main(String[] args)
  {
    A objA = new A();
    B objB = new B();
    
    if(objB instanceof A)
      System.out.println("objB is an A.");  //會印這一行
    else
      System.out.println("objB is not an A.");
      
    if(objA instanceof B)
      System.out.println("objA is a B.");
    else
      System.out.println("objA is not a B.");  //會印這一行
  }
}

「has a」的觀念

//A.java
public class A
{
  private B _objB;  //A類別裡面擁有B
}

//B.java
public class B
{
  public String cAddress;
}

我們都知道子類別一定擁有父類別的所有公開成員,但是父類別並不會繼承子類別所有的公開成員(廢話)。因此如果在確認彼此的「is a」關係下,向上轉型(子→父)的風險永遠比向下轉型(父→子)的風險小。事實上,你根本不可能直接在程式碼中進行向下轉型的動作,除非你先把子類別向上轉型,然後再做一次向下轉型。(脫褲子放屁)

public static void main(String[] args)
{
  String a = new String("TEST1");
  //Upcasting
  Object o1 = a;
  System.out.println(o1);
  
  //編譯時期就錯誤了 Downcasting ERROR!
  //因為「Object is not a b」
  //String b = new Object();
  
  //Downcasting RIGHT!
  String b = new String("TEST2");
  //因為「b is an Object」,因此會自動做Upcasting,要不要打(object)b都可以。
  Object o2 = b;
  //這裡就是真正所謂的向下轉型(Downcasting)
  String c = (String)o2;
  System.out.println(c);
}

向下轉型(Downcasting)在我的程式設計經驗中幾乎完全用不上,所以能夠避免就避免掉。且無論如何,如果要使用向上或向下轉型,勢必都要面對與承擔執行期(Runtime)出錯的風險。

Java SCJP Upcasting Downcasting Polymorphism