多型:同一行為擁有多種表現形式。同一介面,使用不同實例執行不同操作。

現實例子:按下 F1 鍵
- Flash 環境 → AS3 幫助文件
- Word 環境 → Word 幫助
- Windows 環境 → Windows 說明與支援
同一事件在不同物件上產生不同結果。
Parent p = new Child();)呼叫多型方法時:先檢查父類別是否有該方法(無則編譯錯誤),再調用子類別同名方法。
public class Test {
public static void main(String[] args) {
show(new Cat());
show(new Dog());
Animal a = new Cat(); // 向上轉型
a.eat(); // 呼叫 Cat 的 eat
Cat c = (Cat)a; // 向下轉型
c.work(); // 呼叫 Cat 的 catchMouse
}
public static void show(Animal a) {
a.eat();
if (a instanceof Cat) {
Cat c = (Cat)a; c.work();
} else if (a instanceof Dog) {
Dog d = (Dog)a; d.work();
}
}
}
abstract class Animal { abstract void eat(); }
class Cat extends Animal {
public void eat() { System.out.println("吃魚"); }
public void work() { System.out.println("抓老鼠"); }
}
class Dog extends Animal {
public void eat() { System.out.println("吃骨頭"); }
public void work() { System.out.println("看家"); }
}
吃魚 抓老鼠 吃骨頭 看家 吃魚 抓老鼠
子類別重寫父類方法時,子類物件呼叫該方法會執行子類版本。若需呼叫父類版本,需用 super。
public class Employee {
public void mailCheck() { System.out.println("郵寄支票給:" + name + " " + address); }
}
public class Salary extends Employee {
public void mailCheck() {
System.out.println("Salary 類的 mailCheck 方法");
System.out.println("郵寄支票給:" + getName() + ",薪資:" + salary);
}
}
public class VirtualDemo {
public static void main(String[] args) {
Salary s = new Salary("員工A", "北京", 3, 3600);
Employee e = new Salary("員工B", "上海", 2, 2400);
s.mailCheck(); // Salary 版本
e.mailCheck(); // 編譯期看 Employee,執行期跑 Salary 版本
}
}
使用 Salary 的引用調用 mailCheck -- Salary 類的 mailCheck 方法 郵寄支票給:員工A ,工資為:3600.0 使用 Employee 的引用調用 mailCheck-- Salary 類的 mailCheck 方法 郵寄支票給:員工B ,工資為:2400.0
此為虛擬方法調用:編譯期依參考型別驗證,執行期依實際物件型別分派。Java 所有方法預設皆為虛擬方法。