ポリモーフィズム

ポリモーフィズム

ポリモーフィズム=同名のメソッドで異なる挙動を実現すること。

<?php
class Figure {
    protected int $width;
    protected int $height;

    public function __construct(int $width, int $height) {
        $this->width = $width;
        $this->height = $height;
    }

    public function getArea(): int {
        return 0;
    }
}

class Triangle extends Figure {
    public function getArea(): int {
        return $this->width * $this->height /2;
    }
}

class Square extends Figure {
    public function getArea(); int {
        return $this->width * $this->height;
    }
}
 ?>

Figureクラスを継承するTriangleとSquareで同盟のgetAreaをオーバーライドし、それぞれ異なる式で面積を求めている。同じ目的の機能を呼び出すためにクラスごとに異なる名前を覚えなくてもいい。

<?php
$tri = new Triangle(5,10);
$squ = new Square(5,10);

print $tri.getArea(); // 25
print $squ.getArea(); // 50
 ?>

ただし、この状態ではTriangle, SquareクラスにおいてgetAreaメソッドが実装される保証がない。

抽象メソッドと抽象クラス

そこで、以下の仕組みでスーパークラスとサブクラスで同名メソッドを定義することを強制する。

  • 抽象メソッド:それ自体が機能を持たず、サブクラスがオーバーライドによって機能を提供しなければならないメソッド。サブクラスでオーバーライドしない場合エラーが出る。
  • 抽象クラス:抽象メソッドを含んだクラス。 以下のように'abstract'と書き加えることで実装。
<?php
abstract class Figure {
    ...
    abstract protected function getArea(): int;
}
?>

ただし、この場合TriangleクラスとSquareクラスがお互いにとって不要なメソッドまでオーバーライドする必要が出てくる。
(多重継承が許されていない=ポリモーフィズムに関する機能をすべて1つの抽象クラスに定義しなければいけないため)。

インターフェイス

そこで、クラスの代わりにインターフェイスを実装(継承)する。
インターフェイス=配下のメソッドがすべて抽象メソッドであるクラス。以下の点でクラスと異なる。

  • 中身を持つメソッドやプロパティを定義できない。配置できるのは抽象メソッドと定数だけ。
  • abstract修飾子やアクセス修飾子を指定できない。
  • 多重継承が可能。つまりサブクラス側では必要なメソッドを含むインターフェイスを選択的に継承できる。
<?php
interface Figure {
    function getArea(): int;
}

class Triangle implements Figure { // カンマ区切りで複数のインターフェイスを継承できる
    // インターフェイスではプロパティやコンストラクタの定義はできないのでサブクラスに記述
    protected int $width;
    protected int $height;
    
    public function __construct(int $width, int $height) {
        $this->width = $width;
        $this->height = $height;
    }
    
    public function getArea(): int {
        return $this->width * $this->height /2;
    }
}

 ?>