new self();とは PHPで意味ですか?


110

私はこのようなコードを見たことがありません:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

それは同じnew className()ですか?

編集

クラスが継承の場合、どのクラスを指しますか?



@stereofrog、シングルトンパターンを放棄する必要があるということですか?
user198729 2010年

ああ、私はこの点に同意する傾向があります。シングルトンは工場で置き換える必要があります
user198729

@stereofrogシングルトンは単体テストにとって有害で​​す。ある呼び出しから次の呼び出しに状態が変化するものに対して不変のテストを行うことは非常に困難です。
David

残念ながら、この方法は拡張されません。この関数が定義されたクラスの新しいオブジェクトが常に提供されます。
2016年

回答:


211

self それが書かれているクラスを指します。

したがって、getInstanceメソッドがクラス名のMyClass場合、次の行:

self::$_instance = new self();

と同じようになります:

self::$_instance = new MyClass();



編集:コメントの後にいくつかの情報を追加します。

互いに拡張する2つのクラスがある場合、2つの状況があります。

  • getInstance 子クラスで定義されています
  • getInstance 親クラスで定義されています

最初の状況は次のようになります(この例では、不要なコードをすべて削除しました。シングルトンの動作を取得するには、コードを再度追加する必要があります)*:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

ここでは、次のものが得られます。

object(MyChildClass)#1 (0) { } 

意味selfの手段をMyChildClass-すなわち、それが書かれているクラス。


2番目の状況では、コードは次のようになります。

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

そして、あなたはこの種の出力を得るでしょう:

object(MyParentClass)#1 (0) { }

どの手段のself手段MyParentClass-つまりここでも、それが書かれているクラス




PHP <5.3では、「それが記述されているクラス」が重要であり、問​​題が発生する場合があります。

そのため、PHP 5.3ではstaticキーワードの新しい使用法が導入されています。これはself、これらの例で使用したとおりに使用できるようになりました。

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

しかし、staticではなくself、次のようになります。

object(MyChildClass)#1 (0) { } 

これは、そのstatic種類が、使用されている(私たちが使用したMyChildClass::getInstance()クラスを指すのであってそれが記述されているクラスを指すのではないことを意味します。

もちろん、self既存のアプリケーションを壊さないようにの動作は変更されていません-PHP 5.3は新しい動作を追加し、staticキーワードをリサイクルしました。


また、PHP 5.3については、PHPマニュアルの「遅延静的バインディング」ページをご覧ください。


@Paul:heu ...は、「自己がエイリアスとして機能する」、または「自己が指すポイント」を意味しました-フランス語で「デザイナー」動詞を使用できます-これは状況の1つだと思います英語で同じ単語を使用するのは良い考えではありません;-(私はこれを修正するために私の答えを編集します;;ありがとう:-)
Pascal MARTIN

あれば何baseclassclassそれはどちらををポイントしていますか?
user198729 2010年

@user:私は自分の回答を編集してself、継承と継承についてもう少し詳しく説明しました。またstatic、PHP 5.3 に関する情報も含まれています。; これがお役に立てば幸いです:-)
Pascal MARTIN

10

これはシングルトンパターンの実装のようです。この関数は静的に呼び出され、静的クラスに変数が$_instance設定されているかどうかを確認します。

そうでない場合は、自身のインスタンスを初期化し(new self())、それをに格納し$_instanceます。

あなたが呼び出す場合className::getInstance()、あなたは取得する1と同じシングルトンパターンの時点ですべての呼び出し、上のクラスのインスタンスを。

しかし、これがこのように行われるのを私は見たことがありません。$_instanceクラスでは何が宣言されていますか?


1
$_instance宣言されているpublic static $_instance;
Atif

7

これは、コンストラクターがインスタンス化されないようにプライベートとして定義されているシングルトンデザインパターンで最もよく使用されます。二重コロン(::)演算子は、クラス内で静的と宣言されているメンバーにアクセスできるため、静的メンバーがある場合は、疑似変数$これは使用できないため、コードは代わりに自分自身を使用します。シングルトンは、データベースコネクタハンドラのようなオブジェクトのインスタンスを1つだけ許可する優れたプログラミング方法です。クライアントコードから、そのインスタンスへのアクセスは、単一のアクセスポイントを作成することによって行われます。この場合、彼はそれに名前を付けましたgetInstance()。getInstance自体は、基本的に新しいキーワードを使用してオブジェクトを作成する関数であり、コンストラクターメソッドがとも呼ばれている。

この行if(!isset(self::instance))は、オブジェクトがすでに作成されているかどうかを確認します。コードが単なるフラグメントであるため、これを理解できません。上部のどこかに、おそらく次のような静的メンバーがあるはずです

private static $_instance = NULL; 

通常のクラスでは、単純にこのメンバーにアクセスしていました。

$this->_instance = 'something';

しかし、宣言された静的なので、代わりに使用する$ thisコードを使用できませんでした

self::$_instance

この静的クラス変数にオブジェクトが格納されているかどうかを確認することにより、クラスは単一のインスタンスを作成するかどうかを決定できるため、設定されていない場合は!isset、つまり静的メンバー$ _instanceにオブジェクトが存在しないことを意味します。新しいオブジェクトを生成$_instanceし、コマンドによって静的メンバーに格納します

self::$_instance = new self();

そしてそれをクライアントコードに返しました。その後、クライアントコードはパブリックメソッドでオブジェクトの単一のインスタンスを喜んで使用できますが、クライアントコードでは単一のアクセスポイントを呼び出す、つまり、getInstance()メソッドもトリッキーなので、次のように呼び出す必要があります

$thisObject = className::getInstance();

理由は、関数自体が静的であると宣言されているためです。


2

はい、それはnew className()(そのメソッドを含むクラスを参照)のようなもので、おそらくコンストラクターがプライベートであるシングルトンパターンで使用されます。


PHPでシングルトンパターンを使用するのはなぜですか?デーモンのようなプログラムで使用しない限り、シングルトンはスクリプトが実行されている間のみ存続し、プログラムとともに消えます。
ILikeTacos 2013年

4
グローバル変数にアクセスするためにイライラしてグローバルを宣言することを避けるために
Sam Adamsh

0

クラスが継承されている場合、子からgetInstance()を呼び出しても、子のインスタンスは提供されません。親インスタンスのインスタンスのみを返します。これは、new self()を呼び出すためです。

子クラスが子クラスのインスタンスを返すようにしたい場合は、getInstance()でnew static()を使用すると、子クラスインスタンスが返されます。これは遅延バインディングと呼ばれます!!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.