Knowledge Log

【Java】同じ命令で違う動き?「ポリモーフィズム」をRPGの例えで攻略しよう

denson
1

はじめに

みなさんどうも、おげんです。

前回は、クラスの機能を効率よく引き継ぐ「継承」についてお話ししました。

同じコードを何度も書かなくて済む「継承」を覚えると、プログラミングがどんどん楽しくなってきますよね。

でも、継承を使いこなしてキャラクター(クラス)を増やしていくと、次にこんな壁にぶつかりませんか?

「戦士も魔法使いも武闘家も、全員に一斉に『攻撃しろ!』って命令を出したい。

でも、一人ひとりの正体を確認して、個別に指示を出すのは面倒すぎる…」

そんな悩みを魔法のように解決してくれるのが、オブジェクト指向の集大成とも言える「ポリモーフィズム(多態性)」です。

今回は、「名前は難しそうだけど、実はめちゃくちゃ便利」なポリモーフィズムについて、RPGを例に解説していきます。

この記事はこんな人におすすめ!
  • 「ポリモーフィズム」という言葉を聞いただけで、拒絶反応が出てしまう人
  • 継承はわかったけど、それをどう実戦で活かせばいいか悩んでいる人
  • たくさんのキャラクターやアイテムを、スマートに一括管理したい人
  • オブジェクト指向の「一番カッコいい使い方」を知っておきたい人
2

ポリモーフィズムって何?

「ポリモーフィズム(多態性)」を一言でいうと、「相手が誰であっても、同じ命令を出せば、それぞれが適切な動きをしてくれる仕組み」のことです。

これだけだと少し抽象的ですよね。RPGの戦闘シーンをイメージしてみてください。

プレイヤーであるあなたは、パーティー全員に「攻撃!」というコマンドを出します。

このとき、あなたは一人ひとりの細かい動きを指示する必要はありません。

  • 戦士に「攻撃!」と言えば、剣で斬りつける
  • 魔法使いに「攻撃!」と言えば、火の玉を放つ
  • 武闘家に「攻撃!」と言えば、拳で殴る

このように、「攻撃しろ!」という命令(メソッド呼び出し)は一つなのに、受け取る相手によって振る舞いが変わる。

これがポリモーフィズムの本質です。

なぜこれが「スマート」なのか?

もしポリモーフィズムがなかったら、プログラムはこんなに大変になります。

「もし相手が戦士なら剣のメソッドを呼んで、もし魔法使いなら魔法のメソッドを呼んで、もし武闘家なら……」と、相手の正体をいちいち確認(条件分岐)しなければなりません。

ポリモーフィズムを使えば、「相手が誰であれ、とにかくCharacterなんだからattack()は持ってるよね!いけ!」と、大雑把(スマート)に指示が出せるようになるんです。

3

Javaでの書き方:親の型で子を扱う

ポリモーフィズムをプログラムで実現する最大のポイントは、「左側(型)は親クラス、右側(インスタンス)は子クラス」という書き方にあります。

ポリモーフィズムを理解するために、まずは前回の「継承」で作ったクラスをおさらいしておきましょう。

// 親クラス:共通の機能を持つ
public class Character {
    String name;
    void attack() {
        System.out.println(name + "の攻撃!");
    }
}

// 子クラス:親を引き継ぎつつ、自分の個性を出す(オーバーライド)
public class Wizard extends Character {
    @Override
    void attack() {
        System.out.println(name + "は魔法を放った!");
    }
}

この「親」と「子」の関係があるとき、Javaではちょっと不思議なインスタンス化ができるようになります。

不思議な代入の形

通常、インスタンスを作るときは Warrior w = new Warrior(); と書きますが、ポリモーフィズムではこう書くことができます。

// 親(Character)の型に、子(Wizard)を代入する
Character hero = new Wizard();

hero.name = "おげん";
hero.attack(); // 実行結果:「おげんは魔法を放った!」

これ、最初に見ると「えっ、型が違うのにいいの?」とびっくりしますよね。

でも、前回の記事で学んだ「is-a関係(戦士はキャラクターの一種である)」が成り立っているからこそ、Javaはこの書き方を許してくれます。

どういう意味があるの?

この書き方のイメージは、「中身は『戦士』なんだけど、とりあえず『キャラクター』として扱うね!」という予約のようなものです。

Character hero1 = new Warrior(); // 中身は戦士
Character hero2 = new Wizard();  // 中身は魔法使い

hero1.attack(); // 実行結果:「おげんの攻撃!」(戦士の動き)
hero2.attack(); // 実行結果:「魔法使いおげんは魔法を放った!」(魔法使いの動き)

どちらも変数(箱)の型は Character なので、プログラム側は hero1hero2 も、「どっちもCharacterなんだから、とにかくattack()という命令は送れるはずだ」と確信を持って指示が出せます。

そして実際に動かしてみると、Javaが「おっと、この箱の中身は実際には魔法使いだったね」と判断して、上書き(オーバーライド)された適切なメソッドを呼び出してくれるんです。

4

リスト(List)で真価を発揮する

「親の型で子を扱う」という不思議な書き方。

これの何がそんなに凄いのかというと、「違う種類のクラスを、一つのリストにまとめられる」という点にあります。

RPGのパーティー編成をイメージしてみましょう。

もしポリモーフィズムを使わなかったら…

戦士は Warrior 型、魔法使いは Wizard 型…と別々の型で管理しなければなりません。

// 別々のリストを作らないといけない
List<Warrior> warriors = new ArrayList<>();
List<Wizard> wizards = new ArrayList<>();

// 全員に攻撃指示を出すのも二度手間
for (Warrior w : warriors) { w.attack(); }
for (Wizard wiz : wizards) { wiz.attack(); }

これでは、新しい職業(武闘家や盗賊)が増えるたびに、リストもループ処理もどんどん増えていってしまいます。

ポリモーフィズムを使った場合!

「みんな違ってみんな『Character』だよね」という考え方を使えば、一つのリストに全員入れることができます。

// 親の型(Character)のリストに、バラバラな子を入れる!
List<Character> party = new ArrayList<>();

party.add(new Warrior()); // 戦士を追加
party.add(new Wizard());  // 魔法使いを追加

// たった一つのループで、全員に一括指示!
for (Character c : party) {
    c.attack(); 
    // 中身が戦士なら剣で、魔法使いなら魔法で勝手に攻撃してくれる!
}

この書き方の凄いところは、指示を出す側(メイン処理)が「相手の正体が誰か」を1ミリも気にしなくていいところです。

「君たちが誰であれ、とにかく Character なんだから attack() はできるよね。

さあやって!」と丸投げするだけで、各キャラクターが自分の個性を発揮して動いてくれます。

こうした「修正に強く、スッキリしたコード」が書けると、周りのエンジニアからも「おっ、わかってるね!」と思われるはずですよ!

5

まとめ:ポリモーフィズムで柔軟なコードへ

今回は、オブジェクト指向の集大成ともいえる「ポリモーフィズム」についてお話ししました。

名前こそ難しそうですが、その正体は「相手が誰であれ、同じ命令で動かせる」という、エンジニアにとって最高に楽ができる仕組みでした。

ポイントを振り返ると:

  • ポリモーフィズム: 同じ命令(メソッド)を送っても、相手によって動きが変わること。
  • Javaの書き方: Character c = new Warrior(); のように、「親の型に子を入れる」のが基本。
  • 最大のメリット: 相手の正体をいちいち確認しなくていいから、リストなどで一括管理できてコードがスッキリする!

最初は「わざわざ親の型に入れる必要ある?」と思うかもしれません。

でも、開発が進んでキャラクターや機能が10個、20個と増えたとき、このポリモーフィズムの本当のありがたさが身に染みてわかるはずです。

「カプセル化」で守り、「継承」で引き継ぎ、「ポリモーフィズム」で自在に操る。

これで、オブジェクト指向の基礎的な武器はすべて揃いました!

これらの武器を少しずつ使いこなして、スマートなエンジニアを目指していきましょう!

今回も最後まで読んでいただき、ありがとうございました!

ABOUT ME
おげん
おげん
駆け出しエンジニア
文系未経験からエンジニアになるために挑戦を開始したアラサー。転職活動を終え、2026年4月からIT企業で勤務予定。自分が学習で苦労した経験を『誰かのための道しるべ』として発信中。
記事URLをコピーしました