2026.08.29Java基礎 #14|ポリモーフィズムTECH BLOG

Java基礎 #14|ポリモーフィズムとは?同じメソッドで異なる動作を実現する

この記事でわかること

  • ポリモーフィズムとは何か
  • 継承とポリモーフィズムの関係
  • 親クラス型の変数で子クラスを扱う方法
  • オーバーライドしたメソッドが呼び出される仕組み
  • ポリモーフィズムを利用するメリット

前回のおさらい

前回は、クラスの機能を別のクラスへ引き継ぐ継承について学習しました。

また、親クラスのメソッドを子クラスで書き換えるオーバーライドについても紹介しました。

今回は、この「継承」と「オーバーライド」をさらに活用するポリモーフィズムについて解説します。


ポリモーフィズムとは?

ポリモーフィズムとは、簡単にいうと、
「同じメソッドを呼び出しても、実際のオブジェクトによって異なる動作をさせる仕組み」です。

少し難しく感じるかもしれません。

まずは、これまで学んだ継承を思い出してみましょう。


親クラスと子クラス

例えば、Carクラスを親クラスとして、SportsCarクラスとTruckクラスを作ってみます。

Car
├── SportsCar
└── Truck

Carには「走る」という共通の機能を持たせます。

Carクラス

public class Car {

    public void run() {
        System.out.println("車が走ります。");
    }

}

SportsCarとTruckは、このCarクラスを継承します。


子クラスで動作を変えてみよう

SportsCarでは、高速で走るようにしてみます。

SportsCarクラス

public class SportsCar extends Car {

    @Override
    public void run() {
        System.out.println("スポーツカーが高速で走ります。");
    }

}

Truckでは、大きな荷物を運ぶイメージにしてみましょう。

Truckクラス

public class Truck extends Car {

    @Override
    public void run() {
        System.out.println("トラックが荷物を運びながら走ります。");
    }

}

どちらもCarクラスのrun()メソッドをオーバーライドしています。


ここでポリモーフィズム

ここからがポリモーフィズムのポイントです。

次のコードを見てみましょう。

Car car1 = new SportsCar();
Car car2 = new Truck();

一見すると少し不思議な書き方です。

Car型の変数に、SportsCarやTruckのオブジェクトを代入しています。

しかし、これは継承関係にあるため可能です。


同じrun()を呼び出してみよう

Car car1 = new SportsCar();
Car car2 = new Truck();

car1.run();
car2.run();

実行結果

スポーツカーが高速で走ります。
トラックが荷物を運びながら走ります。

ここがポリモーフィズムの重要なポイントです。

どちらもcar1.run()やcar2.run()として同じrun()メソッドを呼び出していますが、実際のオブジェクトに応じて処理が変わっています。


なぜ動作が変わるの?

car1とcar2は、どちらも変数の型はCarです。

Car car1 = new SportsCar();
Car car2 = new Truck();

しかし、実際に作られているオブジェクトは異なります。

  • car1 → SportsCarオブジェクト
  • car2 → Truckオブジェクト

そのため、run()を呼び出したときには、それぞれのクラスでオーバーライドしたrun()が実行されます。


「型」と「実体」を分けて考えよう

ポリモーフィズムを理解するためには、
「変数の型」と「実際に作られたオブジェクト」を分けて考えることが大切です。

Car car = new SportsCar();

この場合、

  • 変数の型 → Car
  • 実際のオブジェクト → SportsCar

となります。

「Car型だけど、中身はSportsCar」という状態です。


ポリモーフィズムのメリット

では、わざわざこのような書き方をするメリットは何でしょうか?

例えば、車の種類が増えたとします。

Car
├── SportsCar
├── Truck
└── FamilyCar

それぞれの車にrun()メソッドがあるとします。

ポリモーフィズムを利用すると、親クラスの型としてまとめて扱うことができます。

Car[] cars = {
    new SportsCar(),
    new Truck(),
    new FamilyCar()
};

for (Car car : cars) {
    car.run();
}

同じrun()を呼び出しているだけですが、実際のオブジェクトに応じて異なる処理が実行されます。

実行結果の例

スポーツカーが高速で走ります。
トラックが荷物を運びながら走ります。
ファミリーカーがゆっくり走ります。

このように、車の種類を1つずつ判定しなくても、それぞれのクラスに応じた処理を実行できます。


ポリモーフィズムを一言でいうと?

難しく考えず、まずは次のように覚えておきましょう。

「同じ呼び出し方で、オブジェクトによって違う動作をさせる」

今回の例なら、

car.run();

という同じ呼び出し方で、

  • SportsCarなら高速で走る
  • Truckなら荷物を運びながら走る
  • FamilyCarならゆっくり走る

というように動作を変えることができます。


よくある混乱ポイント

① Car型なのにSportsCarを入れられるの?

Car car = new SportsCar();

SportsCarがCarを継承しているため可能です。

「SportsCarはCarの一種」と考えると分かりやすいでしょう。

② Carのrun()が実行されないの?

SportsCarがrun()をオーバーライドしている場合、SportsCarのrun()が実行されます。

Car car = new SportsCar();

car.run();

この場合はSportsCarのrun()が実行されます。


継承・オーバーライド・ポリモーフィズムの関係

ここまでの内容を整理してみましょう。

  • 継承 → 親クラスの機能を子クラスが引き継ぐ
  • オーバーライド → 子クラスで親クラスのメソッドを書き換える
  • ポリモーフィズム → 同じメソッド呼び出しで、オブジェクトごとに異なる処理を実行する

これらは、それぞれ別々の機能というより、組み合わせて利用することで力を発揮します。


まとめ

  • ポリモーフィズムは「多態性」とも呼ばれる
  • 同じメソッドを呼び出しても、オブジェクトによって動作を変えられる
  • 継承やオーバーライドと組み合わせて利用する
  • 親クラス型の変数で、子クラスのオブジェクトを扱うことができる
  • プログラムを柔軟で拡張しやすくできる

Java基礎編の振り返りへ

ここまでで、Javaの基本文法からオブジェクト指向まで、一通り学習してきました。

次回からは、ここまで学んだ内容を一度整理してみましょう。

「知っている」から「使える」へ。

これまで学習した文法や考え方を組み合わせながら、Javaの基礎を振り返っていきます。