![]() |
[1999 年 2 月号] |
[Happy Squeaking!!]
5.ポリモルフィズム
5.2 明示的ポリモルフィズムと暗黙的ポリモルフィズム
実はポリモルフィズムには、2種類あります。明示的なものと暗黙的なものです。
例で説明しましょう。Web上で、本の販売を行うシステムを開発することを考えてみます。
本を著すBookクラスを作成し、クライアント側では、本の値段を取り出して表示する際に、BookのインスタンスにcalculatePrice()というメッセージを送っていたとします。
PassRegister(){ Result result := book.calculatePrice(); }
いままではこれだけで問題なかったのですが、Web上の販売が好評なので新たにCDも扱うようになりました。
CDの場合は、本と違って割り引きを行うことができます。
このためcalculatePrice()では、特定の割引率をかけた値をクライアント側に返さなければなりません。
「特に難しいことはない。単にcalculatePrice()の操作を、CompactDiscクラスに定義すればいいじゃないか」と思われることでしょう。
原則としては確かにそうなのですが、明示的なポリモルフィズムを要求する言語では、これだけではうまくいきません。
CompactDiscとBookの共通のスーパークラスとして、calculatePrice()操作の定義されたなんらかのクラスが必要になるのです。
解決策としては、CalculatableProductといった抽象クラスを用意し、これにcalculatePrice()という定義だけで実装のない操作(抽象メソッド)を定義しておきます。
そのサブクラスとしてBook、CompactDiscを定義し、calculatePriceを各々がオーバーロードすることになります。
このように、明示的なポリモルフィズムは、ポリモルフィズムが有効である範囲を共通のスーパークラスの宣言という形で示します。
スーパークラス、サブクラスの関係がある場合でのみポリモルフィズムが働くというわけです。
PassRegister(){ CalculatableProduct prod; //ポリモルフィズムを有効にする共通のスーパークラスを宣言 Result result := prod.calculatePrice(); }
一方で、暗黙的なポリモルフィズムでは、このような制限はありません。
BookがPublication(出版物)のサブクラス、CompactDiscがMusicMediaのサブクラスであり、お互いに共通のスーパークラスがなかったとしても、それぞれがcalculatePrice()の操作を定義していさえすればいいということになります。
どちらの立場と捕るべきかは一概にはいえず、それぞれに長所、短所があります。
暗黙的ポリモルフィズムの言語では、クライアント側の再利用性は非常に高まることになります。当初は予想されていなかった新たなクラスが、呼び出し先で定義され、そのインスタンスがクライアントにやってきた場合でも、クライアントに変更の必要が生じないからです。
一方で明示的ポリモルフィズムのように、スーパークラスの宣言という形でポリモルフィズムの有功な操作を明示的に宣言し示しておいたほうが、よりわかりやすくなると考えることもできます。また、コンパイラの都合ですが、起動する操作の有効範囲が限定されているので、より効率の高い実行コードを作成できる可能性もあります。
Smalltalkでは、暗黙的なポリモルフィズムを採用する立場をとっています。これは、オブジェクト指向の再利用性、柔軟性を最大限に活かすという設計思想にもとづいたものと考えられます。一方で実行効率の良さを追求すると、C++やJavaのように明示的ポリモルフィズムを採用することになります。
© 1999-2001 OGIS-RI Co., Ltd. |
|