どちらもメソッドの名前を再利用しますが、根本的に異なります。オーバーロード = 同じ名前、異なるパラメータ、同じクラス内、コンパイル時に解決。オーバーライド = サブクラスが親メソッドを同じシグネチャで置き換え、実行時に解決。
どちらもメソッドの名前を再利用しますが、根本的に異なります。オーバーロード = 同じ名前、異なるパラメータ、同じクラス内、コンパイル時に解決。オーバーライド = サブクラスが親メソッドを同じシグネチャで置き換え、実行時に解決。
| オーバーロード | オーバーライド |
|---|
| シグネチャ | 異なる必要がある(パラメータ) | 同一である必要がある |
| 関係 | 同じクラス | 親 ↔ サブクラス |
| 解決される | コンパイル時(静的) | 実行時(動的) |
| 目的 | 利便性 / バリアント | ポリモーフィズム |
class Printer {
void print(String s) { System.out.println(s); }
void print(int n) { System.out.println(n); } // same name, diff param
void print(String s, int times) { /* ... */ }
}
コンパイラは引数の型に基づいてどの print を使用するかを選択します — 継承は関与しません。
class Animal { String speak() { return "..."; } }
class Dog extends Animal {
@Override
String speak() { return "Woof"; } // replaces Animal.speak()
}
Animal a = new Dog();
a.speak(); // "Woof" — runtime picks Dog's version (dynamic dispatch)
よくある間違いは、オーバーライドを意図していたのに誤ってオーバーロードしてしまうことです(例えば、シグネチャのタイプミス)。常に @Override(Java)または override(C#)を使用して、コンパイラが検出するようにしてください。
オーバーライドはポリモーフィズムのエンジンです — "1つのインターフェース、多くの実装"を機能させる実行時メカニズムです。
この違いを理解することで、古典的なバグを防ぐことができます。動作を置き換えたと思っていたのに、実は呼び出されることのない2番目のメソッドを作成していた、というバグです。