PHPオブジェクト指向基礎

ポリモーフィズム

ポリモーフィズムとは

オブジェクト指向のメリットとしてよく言われることの中にポリモーフィズムというのがあります。
日本語では多様性とか訳されます。

要は、異なる動作を同じ操作で実現することです。
家電でたとえてみましょう。
どのような家電も、動かすのにスイッチを押すという操作が共通します。しかし当然、スイッチを押す事による動作は家電ごとに違います。

ポリモーフィズムはこれをプログラミングに取り入れたようなものです。

本来ポリモーフィズムは型と深い関わりがありますが、
PHPにおいてはあまり型が意味を持たないので、Javaとかとは多少性格が異なります。
PHPの場合、一言で言えばクラスは異なっても同じ名前のメソッドでいろんな動きを実現させる事です。
それにはインターフェイスが絡んできます。

ポリモーフィズムの考え方

実は、インターフェイスの説明のところのサンプルコードがまさにポリモーフィズムです。カートと商品の例です。
この例では、カートのメソッドは、引数で受け取る商品クラスが、ある特定のメソッドを必ず持っている前提での処理になっており、それを保証するために商品クラスがインターフェイスを実装する、というものです。

インターフェイスや抽象クラスで、抽象メソッドとする理由はなんでしょう。

それは、必ず存在しなければならない手続きだけど、その中身は実装先のクラス内で好きなようにしていいよ、ってことです。

カートと商品の例だと、カートに商品を追加した瞬間に、商品のapplyPriceDownというメソッドが実行されますが、野菜の場合は常に3割引、肉の場合は特定の日のみ半額、冷凍食品に至っては何もしないというように、それぞれapplyPriceDownでやっている処理はバラバラです。

これがポリモーフィズムです。

タイプヒンティング

PHPでは型の曖昧さが一つの特徴です。
しかし、型を明確にしたい場合ってあります。

例えばインターフェイスのところのカートの例であれば、addProductメソッドは商品クラスのインスタンスを引数で受け取る事が前提になっています。しかし仮にこの引数になんか適当な、たとえば文字列とかを指定したらどうなるでしょう。当然おかしなことになります。

カートクラスにとっては、引数で受け取る変数は商品クラスインスタンスであることを保証したいところです。
それを実現するのが「タイプヒンティング」です。


  
    // 商品追加
    public function addProduct(Meet $product)
    {        
        $product->applyPriceDown();    
        $this->products[] = $product;
    }


カートのaddProductメソッドですが、引数の左にクラス名を記述します。
これで、引数$productはMeetクラスのインスタンス以外は受け付けなくなります。

この例の場合、Meetクラスはいいとしても、Vegetableクラスは受け付けてくれません。
しかし素晴らしいことに、このタイプヒンティングにはインターフェイスを指定する事が出来ます


    // 商品追加
    public function addProduct(IProduct $product)
    {        
        $product->applyPriceDown();    
        $this->products[] = $product;
    }

こうすると、引数にはIProductを実装するクラスのインスタンスならなんでも可能になります。つまりVegetableとMeetとFreezedFoodが可能になるのです。

ポリモーフィズムを意識してクラス設計する上では有効な仕組みです。

ちなみにこのタイプヒンティングにはクラスまたは配列のみ指定できます。普通のstringとかintとかいうような型は指定できません。

タイプヒンティングにより、以下のようなメリットがあるといえます。

  • クラス設計者はインターフェイスの仕様にもとづいてメソッドが作成できる
  • クラス使用者はメソッド実行の際の引数に何を渡せばよいかを調べる必要がない

つまり、クラス設計者の意図がクラス使用者に伝わりやすいという事です。