オブジェクト指向プログラミング

ポリモーフィズム ぽりもーふぃずむ

オブジェクト指向継承インターフェースメソッドのオーバーライド抽象クラス動的ディスパッチ
ポリモーフィズムって何?難しそうな名前だけど…

簡単に言うとこんな感じ!

「同じ操作をしても、相手によって動きが変わる」ってことだよ!リモコンの「再生ボタン」を押すと、DVDプレーヤーなら映像が流れて、音楽プレーヤーなら音楽が流れるよね。呼び出す側は「再生して!」と言うだけで、あとは機器がよしなにやってくれる感じ!


ポリモーフィズムとは

ポリモーフィズム(Polymorphism) とは、オブジェクト指向プログラミングの根幹をなす概念のひとつで、「同じインターフェース(操作の窓口)を通じて、異なる型のオブジェクトが、それぞれ異なる振る舞いをする」性質のことです。語源はギリシャ語の「poly(多)+ morphe(形)」で、直訳すると「多態性」または「多相性」と呼ばれます。

たとえば、動物クラスに「鳴く」というメソッドがあったとします。犬クラスは「ワン!」、猫クラスは「ニャー!」と鳴く――でも呼び出す側のコードは「鳴け」と命令するだけ。どんな動物かをいちいち確認して分岐させる必要がありません。呼び出す側のコードをシンプルに保ちながら、振る舞いだけを差し替えられるのがポリモーフィズムの強みです。

ポリモーフィズムは、カプセル化継承 と並ぶオブジェクト指向の三大原則の一角を担っています。「同じコードで将来追加されるクラスにも対応できる」という拡張性の高さが、大規模なシステム開発や長期メンテナンスで特に力を発揮します。


ポリモーフィズムの種類と仕組み

ポリモーフィズムには大きく分けて以下の種類があります。

種類別名概要典型的な実現方法
サブタイプ多態性実行時多態性親クラスの参照で子クラスのメソッドが呼ばれる継承+オーバーライド
パラメータ多態性ジェネリクス型を問わず同じアルゴリズムが使えるジェネリクス・テンプレート
アドホック多態性オーバーロード同名メソッドを引数の型や数で使い分けるメソッドオーバーロード

実務でもっともよく使われるのは サブタイプ多態性 です。以下のPythonコードで雰囲気をつかんでみましょう。

# 親クラス
class Animal:
    def speak(self):
        raise NotImplementedError

# 子クラスがそれぞれ「鳴き方」を上書き(オーバーライド)
class Dog(Animal):
    def speak(self):
        return "ワン!"

class Cat(Animal):
    def speak(self):
        return "ニャー!"

# 呼び出す側は「Animalのリスト」として扱うだけ
animals = [Dog(), Cat(), Dog()]
for a in animals:
    print(a.speak())   # → ワン! ニャー! ワン!

for ループは「犬か猫か」を知らなくても動きます。これがポリモーフィズムの本質です。

覚え方:「リモコンの再生ボタン」

「再生ボタン(共通インターフェース)を押すと、つないでいる機器(クラス)によって動作が変わる」――このイメージで覚えましょう。呼ぶ側はボタンひとつ、応える側が自分のルールで動く、それがポリモーフィズムです。

動的ディスパッチ:実行時に「誰が動くか」が決まる

ポリモーフィズムが実現される背景には 動的ディスパッチ(Dynamic Dispatch) という仕組みがあります。コードを書く段階(コンパイル時)ではなく、プログラムが動いている段階(実行時)に「このオブジェクトはどのクラスのメソッドを呼ぶか」を決定します。これによって、将来新しいクラスを追加しても既存のコードを一切変えずに対応できます。


歴史と背景

  • 1960年代後半 — Simula 67(世界初のオブジェクト指向言語)が登場。クラスと継承の概念を導入し、ポリモーフィズムの基礎が生まれる
  • 1970年代 — Smalltalkがポリモーフィズムを言語の中核に据え、「メッセージパッシング」という形で洗練させる
  • 1980年代 — C++の普及により、オーバーライド・仮想関数(virtual function)として広く認知される
  • 1995年JavaがインターフェースとポリモーフィズムをWeb時代の主流言語として広める。「同じコードを書かずに済む」という実務上の価値が注目される
  • 2000年代以降 — Python、Ruby、C#、Kotlinなど主要言語すべてがポリモーフィズムを標準的にサポート。デザインパターン(StrategyパターンやFactoryパターン等)の基盤技術として不可欠に

継承・インターフェースとの関係

ポリモーフィズムは単独では成立せず、継承インターフェース と組み合わせて使います。それぞれの役割と関係を整理します。

ポリモーフィズムの実現パターン Animal(親クラス) speak() を定義 Dog(子クラス) speak() → "ワン!" Cat(子クラス) speak() → "ニャー!" 継承(override) 継承(override) 呼び出し側コード animal.speak() と書くだけ 実行時に決定 実行時に決定 インターフェース / 抽象クラス 「speak() という窓口を必ず持て」という契約。継承の代わりに使うことも多い
概念役割ポリモーフィズムとの関係
継承親クラスの属性・メソッドを子が引き継ぐサブタイプ多態性の基盤
オーバーライド子クラスが親のメソッドを上書きポリモーフィズムを実際に動かす仕組み
インターフェース「このメソッドを持つこと」という契約継承なしでポリモーフィズムを実現
抽象クラス一部を未実装にした親クラスインターフェースに近い使い方が可能

ビジネス現場での活用イメージ

システム発注や仕様検討の場面で「ポリモーフィズムを使う設計にしてほしい」という要求は、実は次のような意味を持ちます。

  • 「将来の機能追加が楽になる設計」 ― 今は「メール通知」だけでも、後で「SMS通知」「Slack通知」を追加するとき、既存コードを変えずに済む
  • 「テストが書きやすくなる設計」 ― 本物の決済サービスの代わりにダミークラスを差し込める(モック)
  • 「担当者が変わっても読みやすいコード」 ― 条件分岐(if/switch)が減り、コードがすっきりする
【ポリモーフィズムが活きる場面】

if 通知タイプ == "メール":
    メール送信()              ← ← これが増え続けるとカオスに…
elif 通知タイプ == "SMS":
    SMS送信()
elif 通知タイプ == "Slack":
    Slack送信()

↓ ポリモーフィズムを使うと…

通知オブジェクト.send()       ← 呼ぶ側は1行で済む!
(Emailクラス・SMSクラス・Slackクラスが各自で動く)

関連用語

  • ./044-oop.md — オブジェクト指向プログラミング(OOP)― ポリモーフィズムが属するプログラミングパラダイム
  • ./045-class-inheritance.md — 継承 ― ポリモーフィズムを実現する中心的な仕組み
  • ./047-encapsulation.md — カプセル化 ― OOPの三大原則のひとつ。ポリモーフィズムと並ぶ柱
  • ./048-interface.md — インターフェース ― 継承を使わずにポリモーフィズムを実現する「契約」の仕組み
  • ./049-abstract-class.md — 抽象クラス ― 一部を未実装にした親クラス。ポリモーフィズムの土台として使われる
  • ./050-design-pattern.md — デザインパターン ― StrategyパターンやFactoryパターンなど、ポリモーフィズムを活用した設計のお手本集
  • ./051-override.md — オーバーライド ― 子クラスが親クラスのメソッドを上書きする仕組み。ポリモーフィズムの実働部隊