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;
これはちゃんと動きました。
なんでやねん。。
カテゴリ: