オブジェクト指向の基本 - 多態性
多態性とは
急に用語が難しくなりますが、皆さんは「多態性(Polymorphism)」という用語をご存知でしょうか。 多態性と訳さずに、「多相性」「多型性」などと訳されたり、そのまま「ポリモーフィズム」「ポリモフィズム」または「ポリモルフィズム」といった名称で解説されていることも多いので、そちらの名称で記憶されている方もいらっしゃるかもしれません。
「多態性(Polymorphism)」とは、オブジェクト指向における「実行される処理の実体が、コールされたメッセージではなく、メッセージを受けたオブジェクトによって決定される性質」のことです。また、この性質を使って「同一のメッセージを使って、オブジェクトごとに異なった処理を行わせること」を指して、「多態性」という言葉が使われる場合もあります。
OOPでは、さまざまな場面で、この性質を活かしたコーディングを行うことになります。これは、多態性を活かしたコーディングを行うことで、変更に強く柔軟なコードを実現することが出来るためです。それでは、多態性を利用するメリットについて見て行きましょう。
多態性を利用したコーディング
まずは、Cで書かれた以下のコード例をご覧下さい。
switch (user.category_id) { case USER_CATEGORY_ID_GUEST: Guest_action(user); break; case USER_CATEGORY_ID_MEMBER: Member_action(user); break; default: return -1; }
上記は、利用者(user)の分類(category_id)ごとに振る舞いを分けるような処理をイメージしたコードになっています。Cでコードを書かれている方であれば、シーンは違えど、これと似たようなコードを書いたことが、一度はあるのではないでしょうか。
次に同様のシーンを、多態性を利用して書いた場合の例をご覧ください。
user->action(user);
嘘みたいですが、多態性を利用すると、上記のようなシーンはたった1行で済んでしまいます。少し種明かしをしましょう。前述の通り、多態性を取り入れた場合、実行される処理の実体は、コールされたメッセージではなく、メッセージを受けたオブジェクトによって決定されることになります。上記の場合だと、具体的に何の処理が行われるかは、変数userに何のオブジェクトが格納されているかによって、決定されることになります。
なので、利用者の分類ごとに、actionというメッセージに応答出来るオブジェクトを生成し、それをuserに格納しておけば、あとは格納されたオブジェクトに従って適切な振る舞いが実行される、ということになります。いかがでしょうか、多態性を活かしたコーディングについてイメージが出来てきたでしょうか。
最初に挙げたようなコード例は、Cで書かれたプログラムでとてもよく見かけるものです。しかし、このようなコードは、分類の増減のたびにコードに修正を入れる必要があります。また、それが一カ所に納まらない場合は、さまざまな場所に分岐による判断が発生することになり、それらをずっとメンテナンスしていかなければならなくなってしまいます。このような問題に悩まされたことのある方であれば、多態性を活かしたコーディングのメリットについて、理解してもらえるのではないかと思います。
多態性の実現
一般に、多態性を実現するには、継承の仕組みを利用する方法と、オブジェクト間で共有する一連のメッセージを規定する独自の機構を用意・利用する方法の、2つがとられます。継承の仕組みを利用する方法では、スーパークラスで定義されたメッセージの処理の実体を、各サブクラスで用意することで、多態性を実現します。 独自の機構を用意・利用する方法では、独自の機構を用いて規定されたメッセージの処理の実体を、統一的に扱いたい複数のクラスで用意することで、 多態性を実現します。
それでは、多態性をCで実現していきましょう。今回は、前回実装した継承の仕組みを利用して多態性を実現していこうと思います。