こんにちは。ゆとり(@yutori_techblog)です。
この記事では、オブジェクト指向の三大機能のひとつである「ポリモーフィズム(多様性)」について、ものすごく噛み砕いて分かりやすく解説します!
オブジェクト指向の三大機能についてはご存知ですか?
- カプセル化
- 継承
- ポリモーフィズム(多様性)
この3つがオブジェクト指向の三大要素であり、理解は必須です。
このうち、「カプセル化」と「継承」については、
「カプセル化」は、なんとなくオブジェクトを隠蔽するんだな〜
「継承」は、あるオブジェクトの機能を引き継いだ、新しいクラスを作れるんだな〜
てな感じで、なんとなく理解しやすいと思います。
でも「ポリモーフィズム(多様性)」だけはさっぱりわからない!
って方は結構いらっしゃるのではないでしょうか?
そのような方を対象に、分かりやすく丁寧に解説していきます!
ポリモーフィズムは、三大機能のひとつに入っているだけあって、オブジェクト指向を理解するためには必要不可欠なとても大切な機能ですので、しっかり理解してください。
「ポリモーフィズム」を理解するためには、「継承」や「オーバーライド」に関する知識が必須です。
もしそれらの知識がない方は、こちらの記事で詳しく解説していますので、ぜひご覧ください!↓


ポリモーフィズムとは?
ポリモーフィズムとは、次の2つの機能のことをいいます。
- スーパークラスの変数が、そのサブクラスのインスタンスを受けることができる。
- そのようなスーパークラスの変数は、受けたサブクラスのメソッドが使用される。
読んでも、まったく意味がわからないと思いますので、一つずつ説明します。
機能①:
むかしむかし、すごい人がカメラを発明しました。
//昔ながらのカメラ
class Camera {
}
しかし時代は流れ、いろいろなカメラが発明されました。
//デジタルカメラ
class DigitalCamera : Camera {
}
//スマホのカメラ
class SmartphoneCamera : Camera {
}
ポリモーフィズムの1つ目の機能「スーパークラスの変数が、そのサブクラスのインスタンスを受けることができる」というのは、
//スーパークラスの変数が、
Camera camera;
//そのサブクラスのインスタンスを受けることができる
camera = new DigitalCamera();
という機能です。
普通だったらCamera型の変数にはCamera型の変数しか代入できませんよね?
ところが、Cameraを継承しているDigitalCamera型やSmartphoneCamera型の変数も、Camera型の変数に代入することができますよ、というのがポリモーフィズムの1つ目の機能です。
Camera camera = new Camera(); //もちろんできる
DigitalCamera digitalCamera = new DigitalCamera(); //もちろんできる
SmartphoneCamera smartCamera = new SmartphoneCamera(); //もちろんできる
//以下はポリモーフィズムのおかげでできる例
camera = new DigitalCamera(); //Cameraを継承しているので、DigitalCamera型をCamera型に代入可能
camera = new SmartphoneCamera(); //Cameraを継承しているので、SmartphoneCamera型をCamera型に代入可能
どうですか?簡単ですね!
これで何が嬉しいのかは後で説明しますので、ひとまず2つ目の機能の説明に移らせてください。
機能②:
昔ながらのCameraは、当然ですが写真を撮影する機能があります。
class Camera {
public void Shoot() {
//写真をフィルムに焼き付ける処理
}
}
カメラが出たばかりの頃の人々は、このCameraを使って写真を撮っていました。
Camera myCamera = new Camera(); //新しいカメラを買ったぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!

こうして人々は「写真を撮るにはCameraをShoot();すればいいんだ!」と覚えました。
さて、時代は経過しスマートフォンのカメラが登場しました。
昔のカメラはフィルムに画像を直接焼き込むのに対し、スマートフォンのカメラはメモリーにデータとして写真を保存します。
つまり、撮影時の処理が違います。
しかし、人々は「カメラで撮影するにはShoot()!」と覚えてしまっているため、使い勝手は変えたくありません。
そこで、Shootメソッドをオーバーライドしましょう。
class SmartphoneCamera : Camera {
public override void Shoot(){
//画像をメモリーカードに保存する処理
}
}
※実際にはスーパークラス側(Cameraクラス)でShootメソッドをvirtual指定する必要があります
こうして人々は、使い勝手はそのままに、新しいスマートフォンのカメラで写真撮影を楽しみました。
Camera myCamera = new Camera(); //新しいカメラを買ったぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
//-----時間は経過し…
//新しい「スマートフォンカメラ」が開発された!
myCamera = new SmartphoneCamera(); //カメラをスマートフォンのカメラに変えたぞ!
myCamera.Shoot(); //スマートフォンカメラでも今までと同じ方法で写真が撮れるぞ!

最後の行に注目です。
myCameraは、もともとCamera型ですよね。
Camera型ですが、機能①によってSmartphoneCameraのインスタンスを代入することができます。
この時、Camera型のShoot()メソッドではなく、SmartphoneCamera型で定義されたShoot()メソッドが使われます、というのがポリモーフィズムの2つ目の機能です。
このように、利用者側のコードを全く変更することなく、柔軟に仕様を変更することができました。
これが、ポリモーフィズムを利用する大きな利点です。
もし、ポリモーフィズムを利用しなかった場合、スマートフォンのカメラに買い換えた場合にコードを書き直さなければならなくなります。
Camera myCamera = new Camera(); //新しいカメラを買ったぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
myCamera.Shoot(); //myCameraで写真を撮るぞ!
//-----時間は経過し…
//新しい「スマートフォンカメラ」が開発された!
//ポリモーフィズムを利用しないとこれができない
//myCamera = new SmartphoneCamera();
SmartphoneCamera mySmartphoneCamera = new SmartphoneCamera(); //いちいち専用の変数を定義し直し
mySmartphoneCamera.Shoot(); //撮影するコードも書き直し
このように、ポリモーフィズムを利用しなかった場合、仕様変更のたびに利用者側のコードも毎回買い替えなければならなくなります。
以上、簡単にではありますがポリモーフィズムの例と利点を紹介させていただきました。
皆様のお役に立てれば幸いです。
ポリモーフィズムを適切に利用し、柔軟で変更に強いコードを記述しましょう!