PHP5 クラスでは、プライベート コンストラクターはいつ呼び出されますか?
-
09-06-2019 - |
質問
シングルトンとなる PHP (>= 5.0) クラスを作成しているとします。私が読んだすべてのドキュメントには、クラスを直接インスタンス化できないようにクラスコンストラクターをプライベートにするように記載されています。
したがって、次のようなものがある場合:
class SillyDB
{
private function __construct()
{
}
public static function getConnection()
{
}
}
を実行している場合以外に __construct() が呼び出されるケースはありますか?
new SillyDB()
クラス自体の内部で呼び出しますか?
そもそも、なぜ SillyDB を内部からインスタンス化できるのでしょうか?
解決
__construct()
は、プライベート コンストラクターを含むクラスのメソッド内から呼び出した場合にのみ呼び出されます。したがって、シングルトンの場合は、次のようなメソッドが考えられます。
class DBConnection
{
private static $Connection = null;
public static function getConnection()
{
if(!isset(self::$Connection))
{
self::$Connection = new DBConnection();
}
return self::$Connection;
}
private function __construct()
{
}
}
$dbConnection = DBConnection::getConnection();
クラス自体の内部からクラスをインスタンス化できる/したい理由は、常にインスタンスが 1 つだけ存在することを確認できるようにするためです。結局のところ、これがシングルトンの重要な点です。データベース接続にシングルトンを使用すると、アプリケーションが一度に大量の DB 接続を確立することがなくなります。
編集: @emanuele-del-grande の提案に従って $ を追加しました
他のヒント
以下は、日付/時刻文字列を生成するだけの非常に単純なシングルトンです。
class TheDate
{
private static $DateInstance = null;
private $dateVal;
public static function getDateInstance()
{
if(!isset(self::$DateInstance))
{
self::$DateInstance = new TheDate();
}
return self::$DateInstance;
}
public static function getDateVal()
{
return self::$DateInstance->dateVal;
}
private function __construct()
{
$this->dateVal = strftime("%Y-%m-%d %H:%M:%S");
}
}
次のようなことを行うと、明らかに同じ日付が何度も表示されます。
$date1 = TheDate::getDateInstance();
echo $date1->getDateVal() . "<br />";
$date2 = TheDate::getDateInstance();
echo $date2->getDateVal() . "<br />";
これを実行してもエラーは生成されません。
class NewDate extends TheDate
{
public function __construct()
{
}
}
OK、私は独自のテストをいくつか実行しました。
- サブクラスで独自のコンストラクターを宣言しない場合、インスタンス化しようとすると、スーパークラスのコンストラクターを呼び出そうとするため、致命的なエラーがスローされます。
- DB 接続の場合、おそらく (PHP で) mysqli インスタンスまたは DB 接続によって返されたリソースを返していると思われます。
mysql_connect()
関数 (または他の RDBMS への他のリンク) を使用する場合、インスタンスをプライベートとしてマークしている限り、誰かがそのインスタンスをサブクラス化し、リンクを改ざんする脅威はありません。 - 前にほのめかしたように、誰かが本当にあなたの動作をオーバーライドして複数の接続を作成したい場合は、新しいクラスを作成することでそれを行うことができます。
コードをテストして、マーク、何がわかったのか教えてください。
編集:また、この特定の状況では、なぜ人がサブクラス化されないようにする必要があるのかわかりません。誰かがあなたの PHP コードにアクセスしてそれをサブクラス化できる場合、その人はあなたのコードにアクセスしてそれをコピーし、アクセス修飾子を (何らかの理由で) 適切と思われるものに変更することもできます。
この場合のシングルトンの実際的な有用性は、シングルトンを使用することで、特定の HTTP リクエストに対して常に同じデータベース接続を使用できることです。それはそれを実現します。その他のもの(使用 final
およびプライベート コンストラクターなど) を理論の観点から知ると便利ですが、API 品質のコードを他のプログラマーに配布したい場合はさらに便利ですが、この特定の例の場合、キーワードはバイトを追加するだけです。クラスファイルのサイズ。
ちょっとした指摘:完全を期すために、おそらく クラスをfinalとして宣言します 誰かがこのクラスをサブクラス化し、独自のパブリック コンストラクターを実装することも望まないからです。
(コンパイラがプライベート コンストラクターのオーバーライドを検出した場合は申し訳ありませんが、私は検出しないと思います)