Java ポリモーフィズム完全ガイド:オーバーライド、オーバーロード、動的バインディング
Java におけるポリモーフィズムとは?
ポリモーフィズム(多態性) は、Java のオブジェクト指向プログラミング(OOP)における核心概念です。クラスが継承でリンクされているときに生じ、単一のインターフェースで異なる実体を表現できます。結果として、メソッド呼び出しが実行時の実際のオブジェクト型に応じて異なる実装を呼び出せます。
音声通話、テキスト、画像、メールで通信できるスマートフォンを想像してください。目的(通信)は同じですが、各モードの振る舞いは異なります。これが日常的な意味でのポリモーフィズムです。
学習内容
- Java ポリモーフィズムの定義
- 実践的な OOP 例
- メソッドオーバーライド
- オーバーロード vs オーバーライド
- 動的(実行時)ポリモーフィズム
- 静的 vs 動的ポリモーフィズム
superキーワード
Java ポリモーフィズムの OOP 例
基本クラス Account が deposit() と withdraw() を提供し、2つのサブクラス SavingsAccount と CheckingAccount がこれらをそのまま継承するケースを考えます。操作が同一だからです。

変化する要件への対応
オーバードラフト機能などの新機能が必要になったとき、PrivilegedAccount サブクラスで withdraw() をオーバーライドして新しいロジックを提供でき、既存サブクラスに手を加える必要がありません。これがポリモーフィズムの保守性メリットです。

Java のメソッドオーバーライド
オーバーライドは、サブクラスがスーパークラスで既に定義されているメソッドの独自実装を提供することです。メソッドシグネチャ(名前、パラメータ、戻り値型)は完全に一致しなければなりません。
主要ルール
- オーバーライドメソッドの可視性は広げられる(例:
protected→public)が、狭めることはできない - 戻り値型は同じか共変でなければならない
例:
class Doctor {
public void treatPatient() {
// 共通の治療ロジック
}
}
class Surgeon extends Doctor {
@Override
public void treatPatient() {
// 専門的な外科治療
}
}
public class Run {
public static void main(String[] args) {
Doctor doctor = new Doctor();
doctor.treatPatient(); // Doctor.treatPatient() を実行
Surgeon surgeon = new Surgeon();
surgeon.treatPatient(); // Surgeon.treatPatient() を実行
}
}
オーバーロード vs オーバーライド
| メソッドオーバーロード | メソッドオーバーライド |
|---|---|
| 同じクラス内で同名、異なるパラメータリスト | スーパークラスのメソッドをサブクラスで同一シグネチャで再定義 |
例:void sum(int a, int b); |
例:class X { int sum() { ... } }
class Y extends X {
@Override int sum() { ... }
} |
動的ポリモーフィズム(実行時)
スーパークラスの参照がサブクラスのオブジェクトを指すとき、JVM はメソッド呼び出しを実行時に解決します。これが真のポリモーフィズムです。
Doctor doc = new Surgeon(); doc.treatPatient(); // Surgeon.treatPatient() が実行される
実際に呼び出されるメソッドは参照型ではなく、オブジェクトの実行時型に依存します。
静的 vs 動的ポリモーフィズム
静的ポリモーフィズム(オーバーロード)はコンパイル時に解決され、動的ポリモーフィズム(オーバーライド)は実行時に解決されます。
| 静的ポリモーフィズム | 動的ポリモーフィズム |
|---|---|
| メソッドオーバーロード、コンパイル時バインディング | メソッドオーバーライド、実行時バインディング |
例:void sum(int a, int b); |
例:Doctor d = new Surgeon(); |
super キーワードの使用
サブクラスがスーパークラスのメソッドを拡張する必要があるとき、super で親の実装を呼び出してから独自ロジックを追加します。
class Surgeon extends Doctor {
@Override
public void treatPatient() {
super.treatPatient(); // 基底ロジック
// 外科医固有のロジック
}
}
同様に、super でスーパークラスの protected または public フィールドにアクセスできます。
実践例:継承、ポリモーフィズム、Super
以下のコードを IDE にコピーして出力を観察してください。
public class Test {
public static void main(String[] args) {
X x = new X();
Y y = new Y();
y.m2();
// 継承効果を見るには以下をアンコメント
// x.m1();
// y.m1();
// x = y; // 親参照で子オブジェクト
// x.m1();
// y.a = 10; // エラー: a は private
}
}
class X {
private int a;
int b;
public void m1() {
System.out.println("This is method m1 of class X");
}
}
class Y extends X {
int c;
@Override
public void m1() {
System.out.println("This is method m1 of class Y");
}
public void m2() {
super.m1();
System.out.println("This is method m2 of class Y");
}
}
重要ポイント
- ポリモーフィズムにより、継承を通じてオブジェクトが複数の形を取れる
- メソッドオーバーライドでシグネチャを維持しつつサブクラスで振る舞いを変更
- 動的ポリモーフィズムは実行時にメソッド呼び出しを解決し、柔軟なコードを実現
- 静的ポリモーフィズム(オーバーロード)はコンパイル時、動的ポリモーフィズムは実行時
superキーワードでサブクラスが親メソッドを呼び出したり、protected メンバーにアクセスしたりできる
Java
- C#抽象クラス実践チュートリアル:コード例で理解する設計パターン
- C#インターフェース完全解説:定義、実装例、実践的活用法
- Javaポリモーフィズム完全ガイド:概念、例、ベストプラクティス
- Java OOP概念:基礎、実例、利点を徹底解説
- Java String.length()メソッド:文字列サイズ取得の実例解説
- Java String.charAt()完全解説:構文、戻り値、例外、実例
- Java String.contains()メソッド:部分文字列チェックの実践例
- Java String.endsWith()マスター:文字列サフィックスチェック実例付き
- Java static 完全解説:変数・メソッド・ブロックの実践例
- Java インターフェース vs 抽象クラス:適切な抽象化の選び方
- Java BufferedReader でファイル読み込み:実践ガイドと例