タイトル: オーバーライド
オーバーライドとは
オーバーライド (Override) とは、親クラスのメソッドを子クラスで定義し直すことを指します。「親クラスの処理を一部だけ独自に差し替えたい」ときに使い、Java の多態性 (ポリモーフィズム) を実現する中心的な仕組みです。
|
public class Animal { |
オーバーライドの条件
- メソッドシグネチャが親と同じ (名前・引数の数と型)
- 戻り値の型は親と同じか、共変な (より狭い) 型でも可
- アクセス修飾子は親と同等以上の公開度 (狭めるのは不可)
- throws するチェック例外は親の宣言以下でなければならない
staticメソッドはオーバーライドできず、隠蔽 (Hide) になるprivate/finalメソッドはオーバーライド不可
@Override アノテーション
@Override を付けると、コンパイラが「親に同じシグネチャのメソッドが本当にあるか」をチェックしてくれます。タイプミスや親の API 変更による事故を防ぐため、オーバーライド時は必ず付けるのが現代の Java の鉄則です。
|
@Override |
親メソッドの結果を利用するパターン
親の処理を完全に置き換えるのではなく、親の結果を呼んでから差分処理するには super.メソッド() を使います。
|
@Override |
オーバーライドの禁止 (final)
親クラスのメソッドに final 修飾子を付与すると、子クラスでオーバーライドできなくなります。これは「変えてはいけない振る舞い」を強制する手段として有効です。
|
public class Base { |
クラス自体に final を付与すれば、そもそも継承自体を禁止できます (java.lang.String など)。
オーバーライドとオーバーロードの違い
| 項目 | オーバーライド | オーバーロード |
|---|---|---|
| 関係 | 親 → 子のクラス間 | 同一クラス内 (継承下でも可) |
| シグネチャ | 親と同一 | 引数の数・型・順序が違う |
| ディスパッチ | 動的 (実行時の実型) | 静的 (コンパイル時) |
| 典型用途 | 多態性・振る舞いの差し替え | 同名メソッドの便利な集約 |
詳しくは オーバーロード も参照。
典型的なオーバーライド対象
| メソッド | 用途 |
|---|---|
toString() | デバッグ・ログでのオブジェクト表示 |
equals(Object) / hashCode() | 等価判定・Set / Map のキー用 (セットで実装) |
compareTo(T) | ソート (Comparable) |
Object.clone() | 複製 (使用は慎重に) |
| 抽象クラス・インタフェースのメソッド | 実装の提供 (実質的にオーバーライド) |
動的ディスパッチ (多態性) の例
|
List<Animal> animals = List.of(new Dog(), new Cat(), new Animal()); |
注意点
- @Override を必ず付ける。シグネチャ違いをコンパイラに検出させる
- equals と hashCode はセットでオーバーライド。一方だけ変えると Set / Map で破綻する
- 戻り値型・スローする例外を狭めるのは OK、広げるのは NG
- アクセス修飾子を狭めるのは不可 (
public→protectedはエラー) staticメソッドの「オーバーライド」と見えるものは隠蔽 (Hiding)。実行時の型ではなく宣言時の型で選ばれる- コンストラクタは継承されず、オーバーライドの対象ではない
- 子クラスでのオーバーライド時、親が呼ばれなくなる副作用を見落とさない (テンプレートメソッドの破壊)