MENU
PROFILE

なお

本業×複業 | 20歳 | 18歳でリモートインターン▶︎WEBマーケ会社に新卒で部長 | 国語偏差値37でブログ開設▶︎1年3ヶ月で月10万PV▶︎1年半で売上月70万 | 就活・複業、WEB制作~コンサル相談受付中!

 

今井

20歳 | IT系の記事とアイキャッチ画像を担当しています。情報系の大学に通っていて、現在は3年生。カテゴリ整理中。

ポリモーフィズムとはなにか?超わかりやすく解説します!

この記事はこんなことが書かれています!
  • ポリモーフィズムとはなに?
  • どんなことができるようになるの?
  • ポリモーフィズムのメリットは?

今井

こんにちは!
今井(@ima_maru)です。

最近は「オブジェクト指向」というキーワードをよく聞くようになりました。

これは、いままでのプログラミング手法と異なり、

モノが自主的に作用しあう形でプログラムを組むというようなプログラミング手法

などと言われます。

「こんな難しく言われてもわかんねえよ!」って方。私もそうでした。

私はこの概念を理解するのに、一か月くらいかかりました。

そのくらい理解が難しいものであるということは確かです。

大まかに言って、オブジェクト指向を構成する要素は3つあります。

オブジェクト指向を構成する3つの要素

これら3つはオブジェクト指向の基盤を担っているものです。

オブジェクト指向を理解するならば避けては通れない道でしょう。

今回は、その中でも一番理解が難しいとされる「ポリモーフィズム」について解説します。

全く知らない人は、本当に理解するのに時間がかかるかもしれません。

なので皆さんにより効率的に理解してほしいという想いから初めてプログラミングを学ぶ方にも優しい言葉で、できるだけわかりやすく解説していこうと思います。

オブジェクト指向の3つの特徴の1つのポリモーフィズムというのはどういうものなのでしょうか。

見ていきましょう!

じゃぱざむ運営主
なお

WEBマーケター

なお

nao

プロフィール

20歳 | WEBメディアの会社で部長をやりながら、じゃぱざむ・特化メディア・WEB制作~コンサル・投資・就活相談など幅広くやっています。【働くこと(就活など)に役立つ情報流してます】 Twitterはこちら

ポリモーフィズム(polymorphism

ポリモーフィズムとは、オブジェクトなどのデータ型に関する操作が統一的であることである。

なんて言われますが、正直こんな難しいこと言われてわかる人は少ないと思います。

もっともっと優しい言葉で解説しようと思います。

名前の由来

ポリモーフィズムとは、日本語で「多様性」「多態性」「多相性」と訳すことができます。読み方は、ポリモーフィズムのほかに、ポリモフィズムとも読めるそうです。[r]の発音の問題ですね。

単語の構造的には poly morphism 分けられます。

poly(ポリ)には「多くの」という意味があります。

morphism(モーフィズム)は、簡単に「変化」といえばいいのかなと思います。あるものからあるものへの「変化」を表しています。

以上より、ポリモーフィズム(polymorphism)とは、「多くの」「変化」と直訳することができますね。「多くの変化が可能になる」という意味で「多様性」という言葉が当てはまるのだと思います。

poly(多くの)morphism(変化)→ 『多様性』

ポリモーフィズムとは、実は当たり前のこと?

実は、ポリモーフィズムとは、私たちの生活の中に「当たり前」に成り立っていることなのです。

まずは、難しく考えずにこう考えてください。

「モノ」が「そのモノ」らしく振舞うこと

まずは、簡単な例を出します。

このようにアヒルがいます。

この3匹はそれぞれ、どのように鳴くでしょうか?

これは簡単ですよね。

そして、とても当たり前のように感じると思います。

それでは、ここからプログラミングの話に寄せていきます。

まずは、犬と猫とアヒルのクラスを作り、それぞれに鳴くという関数を作成します。

3匹の動物のクラス
クラス 犬    { 鳴く() {  "ワン"  } };
クラス 猫    { 鳴く() { "ニャー" } };
クラス アヒル { 鳴く() { "クワッ" } };

それぞれの鳴き声を、こんな感じで表してみました。

そして、先ほどの「?は??のように鳴く」という風に表せば、

関数の呼び出し
犬.鳴く();
猫.鳴く();
アヒル.鳴く();

このように書けるでしょう。

そして以下のように関数が実行されるはずです。

  • 犬.鳴く() → “ワン”
  • 猫.鳴く() → “ニャー”
  • アヒル.鳴く() → “クワッ”

ここで考えるわけです。

今井

「鳴く」という動作はみんな共通して持っている。ならば、まとめたほうがきれいになるのでは?

このように考えれば、以下のような処理ができるはずです。

ポリモーフィズムを利用した書き方
動物 = { 犬,猫,アヒル };
for (動物) { 動物.鳴く(); }

こんな感じでしょうか?

動物に犬、猫、アヒルが順に入って、鳴き声という関数を呼び出します。

こう書けば、犬は「ワン」、猫は「ニャー」、アヒルは「クワッ」と鳴くはずですね。

結果として先ほどの3行のコードと同じ処理を、きれいにまとめることができました。

ここで考えてもらいたいのが、どの動物に対しても鳴くという処理が同じ動作しかできないのであれば、この構文が使えないということです。

ポリモーフィズムを利用した書き方
動物 = { 犬,猫,アヒル };
for (動物) { 動物.鳴く(); }

例えば、犬を入れても猫を入れてもアヒルを入れても、すべてにおいて「クワッ」と鳴いたらおかしいですよね?

逆に言えば、「中に入るものによって同じ関数でも違う処理を行える」というプログラミング言語自体の特徴があるからこそ、このような構文が使えるようになるということです。

先ほどの図を使えば、

最初の?によって鳴き声が変わるという特徴があるからこそ成立するのです。

そして、この特徴こそが「ポリモーフィズム」と呼ばれます。

もう一度言います。

「中に入るものによって同じ関数でも違う処理を行える」というプログラミング言語自体の特徴

これこそが「ポリモーフィズム」なのです。

オブジェクト指向プログラミング言語では、この特徴を当たり前のように持っています。

というより、「モノ」を基準として考える=オブジェクト指向言語では、ポリモーフィズムがなくては話にならないのです。

もうここまでくれば、なんとなく理解できるはずです。

はじめに書いた、

「モノ」が「そのモノ」らしく振舞うこと

ということを、オブジェクト指向プログラミングに寄せた表現にすれば、

呼び出した関数が呼び出し元のオブジェクトに適した振る舞いをすること

と言い換えることができます。

この、オブジェクト指向言語が当たり前に持つ特徴、仕組みこそが「難しい」といわれるポリモーフィズムの根本の意味なのです。

わざと難しい表現にすれば、オブジェクトなどのデータ型に関する操作統一的であるというような言い方になるわけです。

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

ざっくりと概要をお話ししたところで、

  • ポリモーフィズムを用いるとどのようなメリットがあるのか?

というところについて解説していきます。

ポリモーフィズムのないプログラミングに比べて以下の点で優れているといえます。

  1. コードがきれいにまとまる
  2. プログラムの変更に強くなる柔軟性

二つのメリットは根幹をみれば、どちらも似たりよったりな部分です。

それぞれ、ポリモーフィズムを利用しない場合と比較して、解説していきます。

コードがきれいにまとまる

ポリモーフィズムを利用すれば、とてもコードがきれいにまとまります

これは実際にコードを見てもらったほうがわかりやすいので、プログラミング言語「C++」を使ってを紹介します。

まず下準備として、人間クラスを継承して、7か国の人をクラスとして作りました。

そして、各国のあいさつを表現した関数「Hello()」をそれぞれ持っていると考えてください。

以下で紹介する2タイプのコードは、どちらも7つの国のあいさつを呼び出す処理です。

それではまずは、ポリモーフィズム利用しない場合。

ポリモーフィズム利用しない場合
//それぞれでHello()関数を呼び出す
american.Hello();
japanese.Hello();
indian.Hello();
korean.Hello();
chinese.Hello();
russian.Hello();
german.Hello();

「ちょっとカッコ悪い!」

つぎに、ポリモーフィズム利用した場合。

ポリモーフィズム利用した場合
//それぞれのオブジェクトのポインタを格納する配列を用意
Human* human[N] = 
{ &american,&japanese,&indian,&korean,&chinese,&russian,&german };

//それぞれでHello()関数を呼び出す	
for (int i = 0; i < N; i++) {
	human[i]->Hello();
}

きれいにまとまった感じが見て取れるでしょうか。(ポインタとかはわからなくて大丈夫です。)

こんな風に、ポリモーフィズムを利用すれば、きれいにまとめることができるのです。

またこれは、変更に強くなる柔軟性も兼ね備えているのです。

変更に強くなる柔軟性

先ほどのコードを再利用します。

ポリモーフィズムを利用した場合
//それぞれのオブジェクトのポインタを格納する配列を用意
Human* human[N] = 
{ &american,&japanese,&indian,&korean,&chinese,&russian,&german };

//それぞれでHello()関数を呼び出す	
for (int i = 0; i < N; i++) {
	human[i]->Hello();
}

ポリモーフィズムを利用しない場合はこれ↓です。

ポリモーフィズムを利用しない場合
//それぞれでHello()関数を呼び出す
american.Hello();
japanese.Hello();
indian.Hello();
korean.Hello();
chinese.Hello();
russian.Hello();
german.Hello();

これは、以下のようなことを引き起こします。

  • このような処理をもう一度したいとき、同じコードをもう一度書く必要がある。
  • 単純にコードが縦長になる。

かっこ悪いし、こんな長々と書きたくないです。またこのような処理がしたいとき、またこのコードを書かないといけなくなるというのが、よくない点でしょう。

例えば、もう一回この関数を呼び出すときに、

ポリモーフィズムを利用する場合
//それぞれでHello()関数を呼び出す	
for (int i = 0; i < N; i++) {
	human[i]->Hello();
}

こう書くのと、

ポリモーフィズムを利用しない場合
//それぞれでHello()関数を呼び出す
american.Hello();
japanese.Hello();
indian.Hello();
korean.Hello();
chinese.Hello();
russian.Hello();
german.Hello();

どっちがいいですかという話です。

クラスが増えた分だけ、ポリモーフィズムを利用していない下のコードのほうが大変になります。

次にすべてのクラスに新たなメンバ関数Hoge()が増えた時を考えてみましょう。

単純に考えてください。以下の二つのコードどちらがいいと思いますか?

ポリモーフィズムを利用しない場合
//それぞれでHello()関数,Hoge()関数を呼び出す
american.Hello();
american.Hoge();
japanese.Hello();
japanese.Hoge();
indian.Hello();
indian.Hoge();
korean.Hello();
korean.Hoge();
chinese.Hello();
chinese.Hoge();
russian.Hello();
russian.Hoge();
german.Hello();
german.Hoge();
ポリモーフィズムを利用した場合
//それぞれでHello(),Hoge()関数を呼び出す	
for (int i = 0; i < N; i++) {
	human[i]->Hello();
	human[i]->Hoge();
}

圧倒的に下のほうが見やすいですし、簡単ですよね。

このように記述量が減ることで、修正が加えやすくなります。

大規模開発の際は、あとから変更する場面が多々あるので、修正がしやすいことに越したことはないでしょう。

最後に

理解や解釈が難しいポリモーフィズムですが、私も最初理解に苦しみましたので、いろんな記事を見るとか、直接触れてみて感じてみるとかするととてもいいと思います。

またメリットなどは個人的な見解も含んでいますので、実際にプログラミングしてみてここは違うんじゃないと思うこともあるかもしれません。一つ参考程度に見てください。

この記事はプログラミングを学び始める方向けに作っていますので、これからプログラミングを始める方に少しでも役に立てれば、参考にしてもらえればと思います。

以上、「ポリモーフィズムとはなにか?超わかりやすく解説します!」でした!

今井

最後までご覧いただきありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です