読者です 読者をやめる 読者になる 読者になる

Best effort JavaScript

×article ○weblog

ポリモーフィズムの初歩を理解する

software architecture

最近オブジェクト指向 という概念の理解が非常に漠然としているなぁ...
と感じたので、オブジェクト指向を特集した日経ソフトウェア2014年11月号を本棚から引っ張り出しました。

この特集にはオブジェクト指向という言葉が誕生する以前、ソフトウェア危機が叫ばれた翌年の1969年、NATOソフトウェア工学会議でエドガー・ダイクストラ氏が「構造化プログラミング」を提唱する所から歴史を辿ることが出来るほか、プログラミングスタイルのパラダイム全体を中立に俯瞰した視点でオブジェクト指向の考え方が解説されており、大変優良な記事だと思います。

雑誌の特集であるが故、
年月の経過と共に読者へ届く機会が減ってしてしまうのは残念です...

さて、前置きはここまでとして、
ポリモーフィズムの初歩理解に入って行きましょう!

以降の内容は自分のポリモーフィズムに対しての理解に、
日経ソフトウェア2014年11月号の内容を引用しています。
より詳細を知りたいと思った方、
オブジェクト指向について理解したいと思った方は、
30ページにオブジェクト指向の網羅的な知識がびっしりと詰まっておりますので、
購入をオススメします。

ポリモーフィズムの語源について

ポリモーフィズムという単語の意味を紐解いて行きましょう。
「polymorphism」を意味のあるレベルに分割すると、

  • 「poly」複数
  • 「morphic」形態を取る
  • 「ism」考え方

となります。

以下疑似コードで、ポリモーフィズムが適用されている状態を見てみましょう。

string = number.StringValue()
// 実際にはNumberToString()が呼ばれる

string = date.StringValue()
// 実際にはDateToString()呼ばれる

{オブジェクト}->{メソッド}形式よりも、
{関数}(引数)形式の方がイメージしやすい方も居るでしょう。

string = StringValue(number)
// 実際にはNumberToString()が呼ばれる

string = StringValue(date)
// 実際にはDateToString()呼ばれる

形式は違いますが、意味の同じ疑似コードを2つ紹介しました。
この疑似コードはポリモーフィズムが適用されています。
何処がポリモーフィズムなのでしょうか?

ポリモーフィズムとは、

  • 同名のメソッドを呼び出した時、オブジェクトの状態によって異なる処理が実行される

という状態を指します。

どういう事なのか、先ほどの疑似コードで説明して行きましょう。

string = number.StringValue()
// 実際にはNumberToString()が呼ばれる

このコードはnumber(数値)オブジェクトの、Stringvalue()メソッドを呼び出しています。
StringValue()は数値を文字列に変換(例えば、10を"10"に)したものを返却するメソッドです。
// 実際にはNumberToStringが呼ばれるとコメントにあるように、
この疑似言語は数値型を文字列型に変換する為にNumberToString()メソッドを呼び出す必要がありますが、
例ではNumberToString()をラップ*1したStringValue()を呼び出しています。
この手法によってポリモーフィズムを実現している訳ですが、
どういう事なのか、次の例を見て行きましょう。

string = date.StringValue()
// 実際にはDateToString()呼ばれる

今度はdate(日付)オブジェクトに対してStringValue()を呼び出しています。
// 実際にはDateToString()呼ばれるのコメント通り、この疑似言語では日付型を文字列型に変換するにはDateToString()を呼び出す必要がありますが、
DateToString()をラップしたStringValue()を呼び出しています。

2つの疑似コードをもう一度並べて見てみましょう。

string = number.StringValue()
// 実際にはNumberToString()が呼ばれる

string = date.StringValue()
// 実際にはDateToString()呼ばれる

片方を個別に見ていた時はNumberToString()やDateToString()をStringValue()でラップする意味がいまいち分かりませんでしたが、
並べてみると数値型にも、日付型にも同じメソッドで文字列に変換出来ている事に気がつくでしょう。

文字列への変換は一律でStringValue()を呼び出せば良く、呼び出し元はオブジェクトの型を考慮する必要が無い状態、すなわちポリモーフィズムが適用された状態です。

先ほどのポリモーフィズムの定義をもう一度見てみましょう。

  • 同名のメソッドを呼び出した時、オブジェクトの状態によって異なる処理が実行される

これは状態の異なる(例では型)オブジェクトに対して同名のメソッドを適用できると言い換える事が出来ます。

これによってどんなメリットがあるのかというと、
呼び出し元が楽になります。

今回の例では呼び出し元とは各種オブジェクトを文字列に変換するコードを書いているプログラマで、
オブジェクトを文字列に変換したい時は数値型であろうと日付型であろうとStringValue()を呼べば良く、
型の違いに気を払う必要が無くなります。

呼び出し元が楽になる事、
異なる状態のオブジェクトに対して同一のメソッドを適用出来る事を利用した一連のテクニックがポリモーフィズムの利点です。

今回はオブジェクトの状態の違いに型を例に出して説明していましたが、
違う型のオブジェクトに対して同じメソッドを呼び出すだけがポリモーフィズムではありません。

別の例について知りたくなった方は、
GoFデザインパターンStrategyパターンを調べてみると良いでしょう。