1. ホーム 
  2. 備忘録 
  3. PHP

抽象化

クラスの抽象化

PHP には抽象クラスと抽象メソッドの機能があり、抽象化を行うには abstract の修飾子を使用する

1つ以上の抽象メソッドを持つ全てのクラスは抽象クラスとなる(全てのメソッドが抽象メソッドである必要はない点に注意)

抽象クラスのインスタンスは生成することができず、抽象メソッドはシグネチャを宣言するのみで、実装を定義することはできない

ではなぜこの機能があるかというと、抽象クラスから継承してクラスを作成する際に、親クラスで宣言された抽象メソッドの実装を強制することができるからである

下記に抽象クラスを使った実装例を載せておく

abstract class Animal
{
  // 拡張クラスにこのメソッドの定義を強制する
  abstract protected function getText();
  abstract protected function getDecorateText( $prefix, $suffix );

  // 共通メソッド
  public function call()
  {
    echo $this->getText() . PHP_EOL;
  }
}

class Dog extends Animal
{
  // protected -> protected なのでOK.
  protected function getText()
  {
    return 'ワンワン!!';
  }

  // protected -> public でアクセス権を緩めているのでOK
  // 引数の個数などは親クラスの状態から変更できない
  // 引数の名前は変えられるが、名前付き引数で渡された場合に問題が起きてしまうので親クラスと合わせておくのが無難である
  public function getDecorateText( $prefix, $suffix )
  {
    return "{$prefix} ワオーン!! {$suffix}";
  }

  // もちろん親の抽象クラスで定義された以外の関数も追加できる
  public function bark()
  {
    echo 'バウバウ!!';
  }
}

$dog = new Dog();
$dog->call(); // ワンワン!!
echo $dog->getDecorateText('>>', '<<') . PHP_EOL; // >> ワオーン!! <<
$dog->bark(); // バウバウ!!

インターフェイスとの違い

まず感覚的な部分から違い(使い分け)を書くと、

・インターフェイスはオブジェクトの内部と外部を仲介する意味があり、不特定のクラスで共通の仕様として定義したいときに使用する
・抽象クラスは対象とするオブジェクトがある程度決まっており、オブジェクトの骨組みとして定義したいときに使用する

といったイメージである



感覚だけでは実際使うときに少し迷ってしまうところもあるので、機能としての違いも説明しておく

まず共通の仕様だが

・定数を定義できる
・自身をインスタンス化することはできない
・子クラスにメソッドの実装を強制することができる

といった点が挙げられる



次にインターフェイスだが

・アクセス修飾子は public のみ
・1つのクラスに対して複数のインターフェイスを実装できる
・実装を伴うメソッドやプロパティの定義はできない

といった違いがあり、抽象クラスのほうは

・アクセス修飾子は自由につけられる
・1つのクラスに対して複数の抽象クラスは継承できない
・実装を伴うメソッドやプロパティを定義できる

という違いがある



これらをふまえて、インターフェイスと抽象クラスのどちらを使うのが適切か都度判断していきたい


    参考文献

  1. 公式ドキュメント