タイトルが雑
コード
2017/3/8 0:13 追記
コメントで指摘を頂きました。下記のコードは正しく動作しません。
- 生成されたオブジェクトを比較するとfalseとなる
- 他のクラスから継承させると親クラスとなる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で確認しました。
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 のようにして新しいオブジェクトを作成することができます。
公式のドキュメントはちゃんと読むべきですね。
まとめ
- クラス内で自身のオブジェクトを生成する場合はself、static、parentが使える。
- 継承されることを考慮するならstaticを使う。
PHP: 遅延静的束縛 (Late Static Bindings) - Manual - 書いたコードはちゃんと検証する。