web-dev-qa-db-ja.com

静的メソッド内からクラスインスタンスを作成する

タイトルのとおり、同じクラスの静的メソッド内からクラスのインスタンスを作成したいと思っています。これまでのところ、私は次のようなことをすることで私ができることを理解しました:

class Foo{

 public $val;

 public static function bar($val){
  $inst = new Foo;
  $inst->val = $val;
  return $inst;
 }

}

したがって、これを行うことができます。

$obj = Foo::bar("some variable");

それは素晴らしいです。

さて、質問です。私が知らない、これを行う簡単な方法、または同じ結果を達成するためのショートカットはありますか?この方法でインスタンスを作成することの利点または欠点はありますか?

ありがとう。

41
daniel

彼らはあなたがそれをやっている方法で結構です。あなたが同様にあなたの人生をより簡単にすることができるいくつかの他の事柄があります。

  1. クラス名をハードコーディングしないでください。 5.3以降を使用している場合は、キーワード static を使用します。このようにして、クラスを拡張する場合、新しい関数はそのクラスもインスタンス化できます。

    _public static function bar($var) {
        $obj = new static();
        $obj->var = $var;
        return $obj;
    }
    _

    その後、何もオーバーライドする必要なく、拡張クラスで使用できます。

  2. _$var_を、構築後に設定するのではなく、コンストラクタを通じて渡す必要があるかどうかを判断します。オブジェクトがそれに依存している場合は、それを要求する必要があります。

    _public function __construct($var) {
        $this->var = $var;
    }
    _

    この方法では、変数を設定しないとオブジェクトをインスタンス化できません。

  3. 静的メソッドを通じてクラスのインスタンス化を強制します。そこで何かする必要がある場合は、コンストラクタを保護またはプライベートにしてください。そうすれば、誰かが静的メソッドをバイパスすることはできません。

    _protected function __construct() {}
    private function __construct() {}
    _

それが役に立てば幸い...

編集:上記のコメントに基づいて、 Singleton Design Pattern を実装しようとしているように聞こえます。なぜそれが素晴らしいアイデアではないのか、それが悪いことをするのかについての情報はたくさんあります。それにも用途があります。

しかし、正確に何をしているのかによっては、他にも役立つパターンがいくつかあります。

  • 同じ手順を使用して異なるオブジェクトを作成しようとしている場合は、 Factory Method を使用できます。
  • すべてのオブジェクトが同じように始まり、その後カスタマイズされる場合、 プロトタイプパターン を使用できます。
  • オブジェクトを作成するのに特にコストがかかる場合は、 Object Pool を使用できます。

ただし、考慮すべきことの1つは、PHPオブジェクトはかなり軽量であることです。そのオーバーヘッドのためだけに新しいオブジェクトを作成しないようにしないでください。データベースクエリやファイルシステムアクセスなどの重いことは行わないでください。 fooのコンストラクターが特に重い場合を除いて、new Foo()の呼び出しについて心配する必要はありません...

87
ircmaxell

これは単純なファクトリメソッドパターンのように見えます。

あなたには素晴らしい利点があります。将来、異なる実装の使用を開始したいとします(ただし、同じことを行います)。ファクトリを使用すると、作成者メソッドを変更するだけで、複雑なシステムの多くの場所で作成されるすべてのオブジェクトを変更できます。これは、外部クラスを使用した方が簡単に機能することに注意してください(以下の最初のリンクにあるように)。

現在の状態を維持しながら、このクラスをサブクラス化してメソッドをオーバーライドし、より複雑なオブジェクトを作成することもできます。これはあなたがここで達成したいことではないと思います。

とにかく、これはテスト駆動開発、抽象化、および他の多くの優れた機能を有効にするのに適しています。

リンク:

  1. Phpパターン
  2. ウィキペディアのファクトリメソッドパターン
3
Pedro Loureiro

オブジェクトを作成するだけの場合、これはあまり役に立ちません。コンストラクタを呼び出すだけです。しかし、もっと複雑なことをしている場合(ある種のシングルトンパターンから始めたが、この例にすべての詳細が含まれていない場合など)は、次のようになります。

これはほぼ正しいように聞こえます。このようなデフォルトの方法で作成されたオブジェクトを防止したい場合:

$obj = new Foo("Some Variable");

プライベートコンストラクターを追加できます。

class Foo{

 public $val;

 private __construct(){}

 public static function bar($val){
  $inst = new Foo;
  $inst->val = $val;
  return $inst;
 }
}

次に、静的クラスの使用を強制します。関数にvalを設定する必要がなくなった可能性があるため、値コンストラクターをプライベートコンストラクターに追加するだけで、他のこと(おそらく、ある種のシングルトンパターンのチェックなど)を行うことができます。 「バー」機能

0
Nanne