Javaポリモーフィズム完全ガイド:概念、例、ベストプラクティス
Javaポリモーフィズム
明確な説明と実践的なコード例でJavaのポリモーフィズムを探求し、コードの柔軟性と再利用性をどう高めるか理解します。
ポリモーフィズム——オブジェクト指向プログラミングの不可欠な柱——は、単一のエンティティが複数の形を取り得ることを意味します。
つまり、同じエンティティ(メソッド、演算子、オブジェクト)がコンテキストに応じて異なる操作を実行できるということです。
例:Javaポリモーフィズム
class Polygon { // 図形を描画するメソッド public void render() { System.out.println("Rendering Polygon..."); } } class Square extends Polygon { // Squareを描画 public void render() { System.out.println("Rendering Square..."); } } class Circle extends Polygon { // Circleを描画 public void render() { System.out.println("Rendering Circle..."); } } class Main { public static void main(String[] args) { // Squareオブジェクトを作成 Square s1 = new Square(); s1.render(); // Circleオブジェクトを作成 Circle c1 = new Circle(); c1.render(); } }
出力
Rendering Square... Rendering Circle...
上記例では、スーパークラスPolygonと2つのサブクラスSquare、Circleを作成しました。render()メソッドは両サブクラスに継承されますが、各々が図形固有の描画ロジックを提供するためにオーバーライドしています。
重要なポイントは、render()が実際のオブジェクト型に応じて異なる振る舞いをすること——これがポリモーフィズムの本質です。
なぜポリモーフィズムなのか?
ポリモーフィズムにより、開発者はクリーンで一貫したコードを書けます。renderSquare()やrenderCircle()といった別メソッドを定義する代わりに、単一のrender()メソッドが各図形に適応し、冗長性を減らし保守性を向上させます。
別メソッドでも動作しますが、すぐにコード重複と断片化したAPIを招きます。ポリモーフィズムは共通の契約の下で振る舞いを統一し、新しい図形を単にrender()をオーバーライドするだけで統合できるようにします。
注意: print()メソッドもポリモーフィズムを示します——char、int、Stringなどを、複数のオーバーロードなしで出力できます。
Javaでは以下の技法でポリモーフィズムを実現できます:
- メソッドオーバーライド
- メソッドオーバーロード
- 演算子オーバーロード
Javaメソッドオーバーライド
サブクラスがスーパークラスのメソッドと同じシグネチャでメソッドを定義すると、サブクラスメソッドがスーパークラスメソッドをオーバーライドします。これにより同じメソッド名で、オブジェクトの実行時型に基づいて異なる操作が可能になります。
例1:メソッドオーバーライドによるポリモーフィズム
class Language { public void displayInfo() { System.out.println("Common English Language"); } } class Java extends Language { @Override public void displayInfo() { System.out.println("Java Programming Language"); } } class Main { public static void main(String[] args) { // Javaクラスのオブジェクトを作成 Java j1 = new Java(); j1.displayInfo(); // Languageクラスのオブジェクトを作成 Language l1 = new Language(); l1.displayInfo(); } }
出力:
Java Programming Language Common English Language
ここでは、Languageが基底クラス、Javaがサブクラスとして機能します。displayInfo()メソッドは両クラスで定義されますが、各実装がコンテキスト適切な情報を提供します。
実行されるメソッドは実行時に決定されるため、このパターンは実行時ポリモーフィズムと呼ばれます。

注意: 呼び出されるメソッドはプログラム実行中に決定されます。したがって、メソッドオーバーライドは実行時ポリモーフィズムです。
2. Javaメソッドオーバーロード
メソッドオーバーロードにより、クラスは同じ名前だが異なるパラメータリストを持つ複数のメソッドを持てます。コンパイラは提供された引数に基づいてどのメソッドを呼び出すか解決します。
void func() { ... } void func(int a) { ... } float func(double a) { ... } float func(int a, float b) { ... }
この技法により、同じ論理操作が多様な入力を受け入れられます。
例3:メソッドオーバーロードによるポリモーフィズム
class Pattern { // パラメータなしメソッド public void display() { for (int i = 0; i < 10; i++) { System.out.print("*"); } } // 単一パラメータメソッド public void display(char symbol) { for (int i = 0; i < 10; i++) { System.out.print(symbol); } } } class Main { public static void main(String[] args) { Pattern d1 = new Pattern(); // 引数なしで呼び出し d1.display(); System.out.println("\n"); // 単一引数で呼び出し d1.display('#'); } }
出力:
********** ##########
この例では、Patternクラスに2つのオーバーロードされたdisplay()メソッドがあります。パラメータなし版はアスタリスク10個を出力し、charを受け取る版は指定されたシンボルを10回出力します。
コンパイラがコンパイル時にメソッドを選択するため、この形式のポリモーフィズムはコンパイル時ポリモーフィズムと呼ばれます。
注意: 呼び出されるメソッドはコンパイラによって決定されます。したがって、コンパイル時ポリモーフィズムとしても知られます。
3. Java演算子オーバーロード
Javaの演算子はオペランドの型に基づいて異なる振る舞いを示せます。例えば、+演算子は数値で数値加算、文字列で文字列連結を行います。
+は数値加算または文字列連結を実行。&、|、!などの論理・ビット演算子もオペランド型で振る舞いが異なる。
以下は+がオペランドにどう適応するかを示すスニペットです。
1. 数値の場合:
int a = 5; int b = 6; // 数値での+ int sum = a + b; // 出力 = 11
2. 文字列の場合:
String first = "Java "; String second = "Programming"; // 文字列での+ String name = first + second; // 出力 = Java Programming
したがって、+はJavaで加算と連結の両方を実行するようオーバーロードされています。
注意: C++などではユーザー定義演算子オーバーロードが可能ですが、Javaでは組み込み演算子のみに制限されます。
ポリモーフィック変数
プログラム実行中に異なる型のオブジェクトを参照できる変数をポリモーフィック変数と呼びます。Javaではオブジェクト参照がこの振る舞いを可能にし、基底型の参照がサブクラスのインスタンスを指せます。
例:ポリモーフィック変数
class ProgrammingLanguage { public void display() { System.out.println("I am Programming Language."); } } class Java extends ProgrammingLanguage { @Override public void display() { System.out.println("I am Object-Oriented Programming Language."); } } class Main { public static void main(String[] args) { // オブジェクト変数を宣言 ProgrammingLanguage pl; // ProgrammingLanguageオブジェクトを作成 pl = new ProgrammingLanguage(); pl.display(); // Javaクラスのオブジェクトを作成 pl = new Java(); pl.display(); } }
出力:
I am Programming Language. I am Object-Oriented Programming Language.
この例では、参照plが基底型ProgrammingLanguageで宣言されつつ、基底クラスとそのサブクラス両方のオブジェクトが代入されています。これはアップキャストと実行時ポリモーフィズムを示しています。
Java
- Java演算子をマスター:種類、構文、実践例
- Javaインターフェース完全ガイド:概念、実装、ベストプラクティス
- Javaのtry-with-resourcesをマスターする:自動リソース管理の仕組みと活用法
- Javaアノテーション完全ガイド:種類、配置場所、実践例
- Javaアノテーションタイプ完全ガイド:事前定義・カスタム・メタアノテーション
- Java String.length()メソッド:文字列サイズ取得の実例解説
- Java String.indexOf()マスター:部分文字列検索と実践例
- Java String.charAt()完全解説:構文、戻り値、例外、実例
- Java String.endsWith()マスター:文字列サフィックスチェック実例付き
- Java文字列置換マスター:replace()、replaceAll()、replaceFirst()徹底解説
- Javaメソッドオーバーライド: スーパークラスの振る舞いをカスタマイズ