Java - 一個繼承與多型下動態轉型的例子

在這邊要提到的是繼承與多型下的動態轉型應用,透過一個共用的方法,並依據pass的class

name來動態轉型父類別,此實體再呼叫其下相關的getter method取值後得到比較的結果。

首先,我們制訂了一個抽象類別AbstractBook

abstract class AbstractBook{
    public abstract String showInfo();
}

這個抽象類別定義了一個抽像方法,此方法在子類別繼承AbstractBook,必須override來重新

定義他的行為。

子類別 - ReferenceBook
class ReferenceBook extends AbstractBook{
   private String r_publishing;
   private String r_name;
   public String getR_publishing() {
     return r_publishing;
   }
   public void setR_publishing(String r_publishing) {
     this.r_publishing = r_publishing;
   }
   public String getR_name() {
     return r_name;
   }
   public void setR_name(String r_name) {
     this.r_name = r_name;
   }
 
   public String showInfo(){
     return this.getR_name()+"\t參考書("+this.getR_publishing()+")";
   }
} 

另外定義了自行的成員變數r_pubshing為發行日期、r_name為名稱

子類別 - Magazine
class Magazine extends AbstractBook{
   private String m_publishing;
   private String m_name;
   public String getM_publishing() {
     return m_publishing;
   }
   public void setM_publishing(String m_publishing) {
     this.m_publishing = m_publishing;
   }
   public String getM_name() {
     return m_name;
   }
   public void setM_name(String m_name) {
     this.m_name = m_name;
   }
 
   public String showInfo(){
     return this.getM_name()+"\t雜誌本("+this.getM_publishing()+")";
   }
}

另外定義了自行的成員變數m_pubshing為發行日期、m_name為名稱

PS. 發行日期及名稱在這邊由各類別自行定義,配合override's showInfo method來表達該

method要定義的資訊顯示方式。

主體程式

public static void main(String[] args) {
   // TODO Auto-generated method stub
   try{
      System.out.println("書名                \t類別(出版日期)      \t是否出版?");
      System.out.println("===============================================");
  
      AbstractBook obj1 = new Magazine();
      Magazine nobj1 = (Magazine) obj1;
      nobj1.setM_publishing("2015/01/30");
      nobj1.setM_name("空眾英文雜誌");
      isPublished(obj1, Magazine.class, "getM_publishing");
  
      AbstractBook obj2 = new ReferenceBook();
      ReferenceBook robj2 = (ReferenceBook) obj2;
      robj2.setR_publishing("2015/03/17");
      robj2.setR_name("Java初學手冊");
      isPublished(obj2, ReferenceBook.class, "getR_publishing");
   } catch(Exception e){
      e.printStackTrace();
   }
}

public static void isPublished(AbstractBook book,Class<?> myclass,String ...methodName){
   SimpleDateFormat dateformat = new SimpleDateFormat("yyyy/MM/dd");
   Method m = null;
   try{
     Object obj = myclass.cast(book);
     m = obj.getClass().getDeclaredMethod(methodName[0]);
     String cdate = dateformat.format(new Date());
     Date current = dateformat.parse(cdate);
     Date publish = dateformat.parse(m.invoke(obj).toString());
     if(current.after(publish)){
       System.out.println(book.showInfo()+"\tYES");
     }else{
       System.out.println(book.showInfo()+"\tNO");
     }
   } catch(Exception e){
     e.printStackTrace();
   }
}

首先,利用父類別宣告一物件名,並且實體來自其下的子類別

在這邊為is-a關係方式,即Magazine或ReferenceBook is-a AbstractBook

因此參數book可以操作Magazine's method或ReferenceBook's method為多型的一種表現!!

當然,在參數book能夠取用各自子類別的方法時,還必須透過轉型才可以,如下:

Magazine obj = (Magazine) book;

or

ReferenceBook obj = (ReferenceBook) book;

但是,在isPublished method內,為了要通用各個子類別來轉型,所以就要動態轉型的方式。

因此,在參數2將帶入各個子類別的Magazine.class or ReferenceBook.class等類別物件

PS. 以ClassName.class表示 Returns the runtime class of this Object. By Java Doc.

最後,將得到結果如下:


留言