PHPのコンストラクタ、__construct()
。親クラスのコンストラクタを呼び出すときはparent::__construct()
で呼び出せます。では、親の親というか、祖父母というか、2等身以上離れたクラスのコンストラクタを呼び出すにはどうするのでしょう?親クラスのコンストラクタを実行せず、2等身先のコンストラクタを呼び出したい場合です。
対象のクラス名::__construct()
↑のとおりです。感覚的にstaticな呼び出しと同じ書き方なので、プロパティの設定が意図通り動作するのか不安になりますが、大丈夫なようです。
確認したバージョンは7.1.5とか7.3系。5.6系でもいけそう…?
コード例はこちら。C1 -> C21 -> C321
という流れで継承しています。
<?php
class C1
{
// 動作確認用のプロパティ。各コンストラクタで値を設定。
protected $prop;
function __construct()
{
// C1のコンストラクタを実行した証としてC1を設定
$this->prop = "C1";
}
// 動作確認用の出力関数
function echo()
{
echo $this->prop . PHP_EOL;
}
}
// C1を親に持つクラス
class C21 extends C1
{
function __construct()
{
// C21のコンストラクタを実行した証としてC21を設定
$this->prop = "C21";
}
}
// C1を祖父母、C21を親に持つクラス
class C321 extends C21
{
function __construct()
{
// C321のコンストラクタを実行した証としてC321を設定
$this->prop = "C321";
$this->echo(); // -> C321
// C321の親 = C21のコンストラクタ。prop上書き。
parent::__construct();
$this->echo(); // -> C21
// C1のコンストラクタ。prop上書き。
C1::__construct();
$this->echo(); // -> C1
// parentではなくC21と直接指定も可能。prop上書き。
C21::__construct();
$this->echo(); // -> C21
}
}
// C321のコンストラクタを実行
new C321();
余談 系譜にいない先祖クラスのコンストラクタを呼び出したら?
当たり前ですがエラーになります。cannot be called statically
。コード例はこちら。
// C1を親に持つ。C21は系譜に含まれない。C1は前のコード例参照
class C41 extends C1
{
function __construct()
{
// C41のコンストラクタを実行した証としてC41を設定
$this->prop = "C41";
$this->echo(); // -> C41
// C41の親 = C1のコンストラクタ。prop上書き。
parent::__construct();
$this->echo(); // -> C1
// C1のコンストラクタ。prop上書き。
C1::__construct();
$this->echo(); // -> C1
// C21のコンストラクタ。親にいないからエラー
C21::__construct(); // error
$this->echo(); // ↑でエラーなので実行されない
}
}
// C41のコンストラクタを実行
new C41();
おわりに
そもそも親の親のコンストラクタを直接呼び出すべきでない、呼ぶのは親クラスのコンストラクタだけで、その中で祖父母コンストラクタを呼びだすべき…なんですが、横着したいときにでも知ってると便利かも?