PHPのコンストラクタ(__construct)の驚愕の真実
私は漠然と「同じ」だと思っていました。
でも実は、大きな落とし穴があります。
継承するときに問題が発生します。
次のコードを見てください。
問題ないコード
<?php
class Mother
{
public function __construct()
{
echo "私はママよ。\n";
}
}
class Child extends Mother
{
public function __construct()
{
parent::__construct();
echo "ボクはこどもだよ。\n";
}
}
$obj = new Child;
// 出力:
// 私はママよ。
// ボクはこどもだよ。
これはちゃんと動きます。いたって普通のPHP5のコードで、何も問題ありません。
ひとひねりして次のコードはどうでしょうか。
問題ないコードその2
<?php
class Mother
{
public function Mother()
{
echo "私はママよ。\n";
}
}
class Child extends Mother
{
public function __construct()
{
parent::Mother();
echo "ボクはこどもだよ。\n";
}
}
$obj = new Child;
// 出力:
// 私はママよ。
// ボクはこどもだよ。
これもちゃんと動きます。PHP4スタイルとPHP5スタイルが混在していて見た目がちょっと変ですが、 開発の現場ではわりとよくあると思います。
古いフレームワークを使っていたりすると、上のようなコードを書いてしまうことがあります。
ではいよいよ本題。
もうひとひねりして、次のコードはどうでしょうか?
問題のあるコード
<?php
class Mother
{
public function __construct()
{
echo "私はママよ。\n";
}
}
class Child extends Mother
{
public function __construct()
{
parent::Mother();
echo "ボクはこどもだよ。\n";
}
}
$obj = new Child; // エラー!
これはFatal errorになります。"Call to undefined method Mother::mother() "
つまり、mother()メソッドは未定義だと怒られてしまいました。
当たり前だと感じる人もいるかもしれませんが、私は意外な盲点だと感じました。
フレームワークのバージョンを上げたりするとこの問題に遭遇するかもしれませんので、みなさんご注意を。
(ちなみに私はEthna2.3.5→Ethna2.6betaにバージョンアップしようとしてこの問題に気づきました。)
答え:△(子クラスの挙動が異なる場合がある。)
親クラスFooでメソッドFoo()を__construct()に書き換えた場合、子クラスの挙動に影響が出る場合があります。parent:: で親クラスのコンストラクタを呼び出すときは要注意です!(←コレが言いたかった)
おまけ
<?php
class Mother
{
public function Mother()
{
echo "私は母よ。\n";
}
}
class Child extends Mother
{
public function __construct()
{
parent::__construct();
echo "ボクはこどもだよ。\n";
}
}
$obj = new Child;
これはちゃんと動きました。なんでやねん。。
カテゴリ:
PHP