在 Java 多型機制中,類別繼承與介面實作是核心基礎。當子類別繼承父類別或實作介面時,經常會涉及成員變數與成員方法的重寫。然而,這兩者的行為有本質區別:方法支援動態繫結(覆寫),但成員變數不支援覆寫,僅會遮蔽。
以下範例展示 Person(父類別)與 Man(子類別)皆擁有同名屬性 age 與同名方法 say():
public class Person {
public int age;
public void say() { System.out.println("person say..."); }
}
public class Man extends Person {
public int age;
public void say() { System.out.println("man say..."); }
}
Man man = new Man();
man.age = 20; // 20
Person person = man;
person.age = 25; // 25(修改的是父類別變數)
Man m = new Man();
m.say(); // "man say..."
Person p = m;
p.say(); // "man say..."(呼叫子類別覆寫方法)
結論:透過父類別參考指向子類別物件時,方法呼叫的是子類別覆寫版本(多態),但存取變數卻是父類別的版本(靜態繫結)。
從 JVM 記憶體模型理解:
因此,變數不具備多態特性,這是 Java 設計為「欄位不參與多態」的根本原因。
@Override 註解,編譯器可攔截錯誤的方法覆寫,但無法檢測欄位遮蔽。掌握這項差異,能有效避免多態場景下的隱蔽 Bug,寫出更健壯的繼承體系。