クラスの抽象化

PHP には、抽象クラスと抽象メソッドの機能があります。 abstract として定義されたクラスのインスタンスを生成することはできません。 1つ以上の抽象メソッドを含む全てのクラスもまた抽象クラスとなります。 abstract として定義されたメソッドは、そのメソッドのシグネチャを宣言するのみで、 実装を定義することはできません。

抽象クラスから継承する際、親クラスの宣言で abstract としてマークされた 全てのメソッドは、子クラスで定義されなければなりません。加えて、 オブジェクトの継承シグネチャの互換性に関するルール に従わなければいけません。

例1 抽象クラスの例

<?php
abstract class AbstractClass
{
    // 拡張クラスにこのメソッドの定義を強制する
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>

上の例の出力は以下となります。

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

例2 抽象クラスの例

<?php
abstract class AbstractClass
{
    // 抽象メソッドでは、必須の引数だけを定義しています
    abstract protected function prefixName($name);

}

class ConcreteClass extends AbstractClass
{

    // 子クラスでは、親のシグネチャにないオプション引数を定義することもあるでしょう
    public function prefixName($name, $separator = ".") {
        if ($name == "Pacman") {
            $prefix = "Mr";
        } elseif ($name == "Pacwoman") {
            $prefix = "Mrs";
        } else {
            $prefix = "";
        }
        return "{$prefix}{$separator} {$name}";
    }
}

$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>

上の例の出力は以下となります。

Mr. Pacman
Mrs. Pacwoman