目次
ポリモルフィズムは怖くない!みなさんは知らず知らずそれにふれています、すでにポリモルフィズムを実践しています
こんにちは。技術チームの岩谷です。本連載ではオブジェクト指向プログラミング(OOP)をおさらいする連載を書かせていただいています。今回は第六回として「ポリモルフィズム(Polymorphism:多態性)」について説明します。また、その中で「ポリモルフィズムとインターフェースの関係」についても説明します。
私は後輩のみんなから「Javaの本を読んだけれどポリモルフィズムがわかりにくい」という質問をたびたびされます。「ポリモルフィズム」は特別なものではありません。私は「ポリモルフィズム」という直感的でないカタカナ単語がアレルギー的に日本人の理解を妨げていると考えています。実際みなさんがJavaなどOOP言語を使ってプログラムを書いている時に、みなさんはすでにポリモルフィズムにふれています。今回説明させていただく事例をみなさんが以下に目にした時、みなさんは「…知ってるよ。あたりまえに使ってたよ。」と思うでしょう。そんな「あたりまえ」に対してポリモルフィズムというごたいそうな名前がついているのだということを今日の記事で知っていただいて、モヤモヤをすっきりしていただけたらと思います。
まず単語の説明からです。ポリモルフィズム(polymorphism)=polymorph(多形)+ism(イズム)です。前者「多形」という単語は日本人にとって直感的な表現ではありません。以下の説明でもっといい表現をがんばってしますので無視してください。ここでは後者「イズム」が重要です。イズムとは、
イズム:
多く固有名詞の下に付いて、特有な主義・流儀・傾向などの意を表す。「早稲田―」「三菱―」
(出展:小学館提供『デジタル大辞泉』)
ということで、ここでは「流儀」という表現が適当であると考えてください。ポリモルフィズムとは「プログラムにおける流儀」なのです。どんな流儀なのでしょうか?以下に述べます、ハイっ!
ポリモルフィズム=いろんなクラスがあるけれど「同じ目的を持ったメソッドには同じメソッド名をつけましょうよ」という流儀
です!…ほら、みなさんやっぱり「なんだ、あたりまえじゃないか?」と思ってらっしゃいますよね?ここで今日の記事を終わりにしてもいいのですが、私もせっかく筆がのってきたので、もう少し説明に付き合ってください。以下にJavaにおける具体的な説明をします。以下の2つのソースを見比べてください。特に4行目の「toStringメソッド」が両者に共通している事を意識してください。
例1:Date(日付)クラス
1 2 3 4 5 6 |
//日付オブジェクトを生成 Date obj1 = new Date(); //オブジェクトを文字列オブジェクトに変換 String str1 = obj1.toString(); //文字列を画面に出力 System.out.println(str1); |
出力結果:
>Mon Aug 24 15:00:27 JST 2015
例2:Currency(国通貨)クラス
1 2 3 4 5 6 |
//国通貨オブジェクトを生成(通貨対象国は日本) Currency obj1 = Currency.getInstance(Locale.JAPAN); //オブジェクトを文字列オブジェクトに変換 String str1 = obj1.toString(); //文字列を画面に出力 System.out.println(str1); |
出力結果:
>JPY
両者の「toStringメソッド」は「自分自身の内容を文字列で表したい」という「目的」において同じ
上記2つのソースは、実は「2行目」が違うだけで後は全て同じです。例1は日付オブジェクトを生成して画面上に「Mon Aug 24 15:00:27 JST 2015」と表示しています。例2は国通貨オブジェクトを生成して画面上に日本円の通貨コード「JPY」を表示しています。ここでもう一度、4行目の「toStringメソッド」に注目してください。例1のtoStringはDateクラスのメソッドです。対して例2のtoStringはCurrencyクラスのメソッドです。「クラスは違えどメソッド名は同じ」という状況がここにはあります。これが「いろんなクラスがあるけれど同じ目的を持ったメソッドには同じメソッド名をつけましょうよ」という流儀=ポリモルフィズムが実現されている状態なのです。「toStringメソッド」は「自分自身に格納されているデータを文字列で表す」という目的を持っています。例1は日付を文字に、例2は国通貨を文字に、クラスは違えど「自分自身に格納されているデータを文字列で表す」という目的は同じです。「目的が同じなら同じメソッド名をつけよう!」という流儀がここに貫かれているのです。これがポリモルフィズムです。
ポリモルフィズムのメリット:メソッド名を見ればそれが「何を提供してくれる機能なのか?」をシステムの中で「常識化」できる。
では、この流儀に従うとどんな良いことがあるのでしょうか?その答えの前に、ポリモルフィズムの流儀において「ありがちなメソッド」を以下に並べて見ます。
- toString
- equals
- open
- close
- get
- put
これらのどれもがみなさんが使ったことのあるメソッドなのではないでしょうか?そしてなによりも!これらのメソッドを呼び出した処理の結果をみなさんは想像できるのではないでしょうか?実はこれこそがポリモルフィズムのメリットなのです!メソッド名を見れば「そのメソッドが何を提供してくれる機能なのか?」をシステムの中で「常識化」できる事が、ポリモルフィズムの流儀に従うメリットなのです。
「常識化」ではヌルい!ポリモルフィズムの流儀を「強制」したい→ここでやっとインターフェースの登場です!
ここまでで、ポリモルフィズムの流儀について説明させていただきました。逆に言うとここまでは「流儀」の話ししかしていません。ここからはこの流儀をOOPの機能を使ってプログラム上でより強固に実現する方法を説明します。それが「インターフェースの導入」です。以前の記事で私は、インターフェースとは「このクラスは、○×△メソッドを実装します!」という「約束」(=実装強制)であると書きました。これが「ポリモルフィズムの流儀に従うこと」にそのままつながります。すなわちクラスとインターフェースを結びつける=クラスにインターフェースを実装することによって、「常識化」したいメソッドを持つことを「強制」できるのです。「ポリモルフィズムの”流儀”をOOPのインターフェース機能で”強制”にまで高められる」と言いかえてもいいでしょう。JavaのMapインターフェースを思い出してください。Mapインターフェースを実装している有名クラスにはHashMapクラスやHashtableクラス, LinkedHashMapクラスがあります。これらのクラスはMapインターフェースによって「getメソッド」や「putメソッド」を各々が持てと「強制」されています。おそらくHashMapクラスのgetメソッドとHashtableクラスのgetメソッドとは中のプログラムコードは異なるしょう。でも「自身が内部で持っているデータを出力する」という目的は同じです。ゆえにポリモルフィズムの流儀に従ってメソッド名をそろえているのです。ここでもう一度忘れないようにいいます。ポリモルフィズムは、いろんなクラスがあるけれど「同じ目的を持ったメソッドには同じメソッド名をつけましょうよ」という流儀なのです。
「インターフェースのメソッド一覧」には「ポリモルフィズムの流儀」がつまっている
今回はOOPにおけるポリモルフィズムとインターフェースとの関係について説明しました。最後に、今日の説明をインターフェースの視点から言い換えると「インターフェースとは、ポリモルフィズムの流儀をMapの流儀・Listの流儀のように流儀の単位でまとめたもの」と表現できます。みなさんどうかこの記事をお読みになった後にMapインターフェースやListインターフェースなどいろいろなインターフェースのAPIドキュメントを見てみてください。そこでみなさんは「Mapオブジェクトとして実現したい目的」の一覧や「Listオブジェクトとして実現したい目的」など「オブジェクトが果たしたい目的の一覧」が「ポリモルフィズムの流儀に則ったメソッドの一覧」として表されているのを目にする事ができるでしょう。
【本連載について】
- OOPと非OOPの違い|オブジェクト指向プログラミング(OOP)をおさらいしよう(1)
- 継承によってコードを再利用する|オブジェクト指向プログラミング(OOP)をおさらいしよう(2)
- インターフェースとは?~継承とは役割が違う~|オブジェクト指向プログラミング(OOP)をおさらいしよう(3)
- カプセル化とは?~安全なシステムを作る為の配慮~|オブジェクト指向プログラミング(OOP)をおさらいしよう(4)
- 静的型付けと動的型付け~JavaとJavaScriptのJSON処理を比較~|オブジェクト指向プログラミング(OOP)をおさらいしよう(5)
- ポリモルフォズム(多態性)とは?~クラスは違えど同じ目的には同じメソッド名を~|オブジェクト指向プログラミング(OOP)をおさらいしよう(6)