いくつかの静的関数を持つヘルパークラスがあります。クラス内のすべての関数は、1回実行するために「重い」初期化関数を必要とします(コンストラクターであるかのように)。
これを達成するための良い習慣はありますか?
私が考えた唯一のことは、init
関数を呼び出し、それが既に一度実行された場合にそのフローを壊すことでした(静的$initialized
var)。問題は、クラスのすべての関数で呼び出す必要があることです。
静的メソッドの束ではなく、シングルトンの方が適切に処理されるように聞こえます
class Singleton
{
/**
*
* @var Singleton
*/
private static $instance;
private function __construct()
{
// Your "heavy" initialization stuff here
}
public static function getInstance()
{
if ( is_null( self::$instance ) )
{
self::$instance = new self();
}
return self::$instance;
}
public function someMethod1()
{
// whatever
}
public function someMethod2()
{
// whatever
}
}
そして、使用中
// As opposed to this
Singleton::someMethod1();
// You'd do this
Singleton::getInstance()->someMethod1();
// file Foo.php
class Foo
{
static function init() { /* ... */ }
}
Foo::init();
この方法では、クラスファイルが含まれているときに初期化が行われます。自動ロードを使用して、これが必要な場合にのみ(そして一度だけ)発生することを確認できます。
実際には、初期化が必要な(または少なくともコードを実行する必要がある)静的クラスで、パブリック静的メソッド__init__()
を使用します。次に、私のオートローダーでは、クラスをロードするときにis_callable($class, '__init__')
をチェックします。存在する場合、そのメソッドを呼び出します。素早く、シンプルで効果的...
init()
メソッドを一度呼び出して使用を禁止する方法があります。関数をプライベート初期化子に変更し、クラス宣言の後に次のように呼び出すことができます。
class Example {
private static function init() {
// do whatever needed for class initialization
}
}
(static function () {
static::init();
})->bindTo(null, Example::class)();
注:これは、OPが言ったこととまったく同じです。(ただし、コードは表示しませんでした。)ここで詳細を表示し、受け入れられた回答と比較できるようにします。私のポイントは、OPの最初の本能は、私見であり、彼が受け入れた答えよりも優れていたということです。
受け入れられた答えがどれほど高く支持されているかを考えると、静的メソッドの1回限りの初期化に対する「素朴な」答えは、シングルトンの実装よりも多くのコードではないことを指摘したいと思います-そしてhas本質的な利点。
final class MyClass {
public static function someMethod1() {
MyClass::init();
// whatever
}
public static function someMethod1() {
MyClass::init();
// whatever
}
private static $didInit = false;
private static function init() {
if (!$didInit) {
$didInit = true;
// one-time init code.
}
}
// private, so can't create an instance.
private function __construct() {
// Nothing to do - there are no instances.
}
}
このアプローチの利点は、単純な静的関数構文で呼び出すことができることです:
MyClass::someMethod1();
受け入れられた回答で必要な呼び出しとは対照的です。
MyClass::getInstance->someMethod1();
一般的な原則として、クラスをコーディングするときに、呼び出し元をよりシンプルにするために、コーディング価格を一度支払うのが最善です。
すべての回答(これを含む)の中で、私は Victor Nicolletの回答 を好みます。シンプル。追加のコーディングは不要です。理解するための「高度な」コーディングはありません。 (「init」が2回実行されないように、FrancescoMMのコメントを含めることをお勧めします。)
ですから、この答えを書くのは面倒でした。しかし、非常に多くの人々が受け入れられた答えを支持したため、一部の人々は単純な「ナイーブ」なアプローチに気づいていないと結論付けました(ここに示します)。これを出発点として理解してください。
public
静的初期化子が気に入らない場合は、リフレクションを回避することができます。
<?php
class LanguageUtility
{
public static function initializeClass($class)
{
try
{
// Get a static method named 'initialize'. If not found,
// ReflectionMethod() will throw a ReflectionException.
$ref = new \ReflectionMethod($class, 'initialize');
// The 'initialize' method is probably 'private'.
// Make it accessible before calling 'invoke'.
// Note that 'setAccessible' is not available
// before PHP version 5.3.2.
$ref->setAccessible(true);
// Execute the 'initialize' method.
$ref->invoke(null);
}
catch (Exception $e)
{
}
}
}
class MyClass
{
private static function initialize()
{
}
}
LanguageUtility::initializeClass('MyClass');
?>