從 C++ 轉向 Java 的開發者常對「名稱隱藏」行為感到驚訝。在 C++ 中,衍生類別定義同名方法會隱藏基底類別所有同名多載版本;但 Java 採取完全不同的規則:**衍生類別的方法定義不會隱藏基底類別的任何多載版本**。本文將透過程式碼示範這一核心差異,並說明 Java 多載解析的運作邏輯。
| 語言 | 規則 | 結果 |
|---|---|---|
| C++ | 衍生類別定義同名方法 → 隱藏基底類別**所有**同名多載 | 需用 using Base::func 重新引入 |
| Java | 衍生類別定義同名方法 → **不隱藏**基底類別任何多載 | 所有版本皆可見,正常多載解析 |
class Homer {
char doh(char c) { System.out.println("doh(char)"); return 'd'; }
float doh(float f) { System.out.println("doh(float)"); return 1.0f; }
}
class Milhouse {}
class Bart extends Homer {
void doh(Milhouse m) {} // 新增多載,不影響繼承的 doh(char) 和 doh(float)
}
public class Hide {
public static void main(String[] args) {
Bart b = new Bart();
b.doh(1); // 呼叫 doh(int) → 類型提升匹配 doh(float)
b.doh('x'); // 呼叫 doh(char)
b.doh(1.0f); // 呼叫 doh(float)
b.doh(new Milhouse()); // 呼叫 Bart 自己的 doh(Milhouse)
}
}
輸出:
doh(float)
doh(char)
doh(float)
doh(Milhouse) // 假設有印出
觀察重點:
b.doh(1):int 提升為 float,匹配繼承自 Homer 的 doh(float)b.doh('x'):精確匹配繼承的 doh(char)Bart 新增的 doh(Milhouse) **完全不影響** 基底類別的兩個多載版本本文討論的是**多載**(同名、不同參數)。若衍生類別定義與基底類別**完全相同的簽名**(參數型別、順序、數量皆同)且回傳型別相容,則是**覆寫**,此時會發生動態繫結,而非多載解析。Java 允許覆寫,但建議:
@Override 註解,編譯器會驗證確實覆寫理解 Java 「不隱藏多載」的設計決策,能讓你在設計類別階層時更自信地使用多載,避免 C++ 思維帶來的誤區。