LoginSignup
15
14

More than 5 years have passed since last update.

クラス内のメソッドで自身をnewするときはself、static、parentでいける

Last updated at Posted at 2017-03-07

タイトルが雑

コード

2017/3/8 0:13 追記
コメントで指摘を頂きました。下記のコードは正しく動作しません。
1. 生成されたオブジェクトを比較するとfalseとなる
2. 他のクラスから継承させると親クラスとなるmyClassのオブジェクトが返される

完全に私の検証不足です。申し訳ございません。
推測ですが、2についてはコンテキストがmyClass内なのでself()ではmyClassが生成されるのではないかと。staticを使用すれば呼び出し元のオブジェクトが返ると思います。

2017/3/8 さらに追記
コメントで教えていただきました。
比較するとfalseになる問題は私のコード記述ミスでした。メンバ変数にオブジェクトを入れてないので毎回新しいオブジェクトが生成されていました。
継承すると親クラスのオブジェクトが返される問題は、selfではなくstaticを使用することで解決できます。
また、privateやprotectedのメンバ変数を使用すると継承された際にエラーになるため、メソッド内でstatic変数を使用する必要があります。
これらを踏まえてコードを修正しました。教えていただいた方々、本当にありがとうございます。

class myClass
{
    final private function __constructor() {}

    public static function getInstance()
    {
        static $instance;
        if (!$instance) {
            $instance = new static;
        }
        return $instance;
    }
}

実行結果

PHPのバージョンは5.5.38と7.1.1で確認しました。
text
php > class myClass
php > {
php { final private function __constructor() {}
php {
php { public static function getInstance()
php { {
php { static $instance;
php { if (!$instance) {
php { $instance = new static;
php { }
php { return $instance;
php { }
php { }
php >
php > var_dump(myClass::getInstance() === myClass::getInstance());
bool(true)
php >

同じオブジェクトが返ります。

次は継承させてみます。

class myParentClass
{
    final private function __constructor() {}

    public static function getInstance()
    {
        static $instance;
        if (!$instance) {
            $instance = new static;
        }
        return $instance;
    }
}

class myChildClass extends myParentClass {}
php > class myParentClass
php > {
php {     final private function __constructor() {}
php {     
php {     public static function getInstance()
php {     {
php {         static $instance;
php {         if (!$instance) {
php {             $instance = new static;
php {         }
php {         return $instance;
php {     }
php { }
php > 
php > class myChildClass extends myParentClass {}
php > 
php > var_dump(myChildClass::getInstance());
object(myChildClass)#1 (0) {
}
php > 

シングルトンパターンが使われているコードを読んでいて、new myClass()と書かれているのを発見。
同じようなコードが大量にありまして、基底クラスにまとめて継承できそうだったので考えていた時に試しにself()って書いてみたら動いたんです。目から鱗が落ちました。

調べてみたら公式のドキュメントにさらっと書いてありますね。どうやらparentでもできる模様。先に書いたように継承を考慮するならstaticを使用します。
PHP: クラスの基礎 - Manual

クラスのコンテキストにおいては、 new self や new parent のようにして新しいオブジェクトを作成することができます。

公式のドキュメントはちゃんと読むべきですね。

まとめ

15
14
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14