身為初學 Java 的開發者,繼承與多態常讓人感到困惑。本文透過一個媒體庫管理系統的實例,深入淺出說明多態的運作機制。
需建立一個媒體庫,可存放 CD 和 DVD,支援新增與列出所有媒體。由於 CD 和 DVD 共享許多屬性(名稱、播放時間、評論等),採用繼承設計:
Item:封裝共同屬性與方法CD、DVD:繼承 Item 並擴充專屬屬性Database:使用 ArrayList<Item> 統一管理// Item.java - 父類別
public class Item {
private String title;
private int playTime;
private boolean gotIt;
private String comment;
// 建構子、getter/setter、print() 方法
}
// CD.java - 子類別
public class CD extends Item {
private String artist;
private int numOfTracks;
// 覆寫 print() 方法
public void print() {
System.out.print("CD:");
super.print();
System.out.println(":" + artist + ":" + numOfTracks);
}
}
// DVD.java - 子類別
public class DVD extends Item {
private String director;
// 覆寫 print() 方法
public void print() {
System.out.print("DVD:");
super.print();
System.out.println(":" + director);
}
}
// Database.java - 管理類別
public class Database {
private ArrayList<Item> listItem = new ArrayList<>();
public void add(Item item) { listItem.add(item); }
public void list() {
for (Item item : listItem) {
item.print(); // 多態發生的關鍵
}
}
}
在 Database 中宣告 Item item,此變數可指向 Item 或其任一子類別(CD、DVD)的實例。實際指向的物件類型在執行期才決定,這就是多態變數。
將子類別物件指派給父類別變數(如 db.add(new CD(...))),這是安全的,因為子類別擁有父類別的所有特徵。
當子類別覆寫父類別方法(override)時,父類別方法被隱藏。執行 item.print() 時,JVM 會根據 item 實際指向的物件類型,動態調用對應的 print() 方法(CD.print() 或 DVD.print()),而非父類別的 Item.print()。這就是動態繫結的精髓。
透過此例可見,多態讓程式碼更具彈性與擴充性,新增媒體類型時無需修改 Database 類別。