| 維度 | 方法多載 | 方法覆寫 |
|---|---|---|
| 英文術語 | Overloading | Overriding |
| 發生範圍 | 同一個類別內 | 父子類別之間 |
| 方法名稱 | 相同 | 相同 |
| 參數列表 | 必須不同 (型別/個數/順序) | 必須相同 |
| 回傳型別 | 可不同 | 必須相同或為協變型別 (子類型) |
| 存取修飾詞 | 無限制 | 不能比父類更嚴格 (public → protected ❌) |
| 拋出異常 | 無限制 | 不能拋出比父類更廣的檢查型異常 |
| 綁定時機 | 編譯期靜態綁定 | 執行期動態綁定 (多型) |
| 目的 | 方便呼叫者,同名處理不同參數 | 子類特化父類行為,實現多型 |
public class Math {
public static int abs(int a) { return a < 0 ? -a : a; }
public static long abs(long a) { return a < 0 ? -a : a; }
public static float abs(float a) { return a < 0 ? -a : a; }
public static double abs(double a) { return a < 0 ? -a : a; }
}
// 呼叫端
int i = Math.abs(-5); // 呼叫 abs(int)
long l = Math.abs(-5L); // 呼叫 abs(long)
double d = Math.abs(-5.0); // 呼叫 abs(double)
編譯器根據實參型別決定呼叫哪個 abs,零耗能、極易閱讀。
class Employee {
protected double salary;
public void setSalary(double base, double rate) {
this.salary = base * (1 + rate); // 一般調薪公式
}
}
class Sales extends Employee {
@Override
public void setSalary(double base, double rate) {
this.salary = base * (1 + 2 * rate); // 業務提成雙倍
}
}
// 多型呼叫
Employee e = new Sales();
e.setSalary(10000, 0.1); // 實際執行 Sales.setSalary,薪資 = 12000
@Override 註解可在編譯期檢查簽名是否真正匹配父類,強烈建議永遠加上。
Number → 子 Integer),不能任意改。private 方法不可見,子類同名方法只是新方法,非覆寫。class Base {
public void foo(int a) {}
protected void bar(String s) {}
void baz() {} // package-private
}
class Derived extends Base {
public void foo(long a) {} // 1. 多載 (參數型別不同)
public void foo(int a) {} // 2. 覆寫 (完全相同)
protected void bar(String s) {} // 3. 覆寫 (權限相同)
public void bar(String s) {} // 4. 覆寫 (權限放寬 protected→public ✓)
// void baz() {} // 5. 編譯錯誤:權限縮小 (default→private ❌)
public void baz() {} // 6. 覆寫 (權限放寬 default→public ✓)
}
@Override,編譯器幫你擋住簽名不匹配的低級錯誤。