PHPでクラスメンバーを初期化するためのベストプラクティス


10

私のコンストラクタには次のようなコードがたくさんあります:-

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

プロパティ定義でデフォルト値を指定するよりも、これを行う方が良いですか?すなわちpublic $property = default_val?時々、デフォルト値のロジックがあり、いくつかのデフォルト値は他のプロパティから取得されるため、コンストラクターでこれを行っていました。

デフォルト値のすべてのロジックが分離されるようにセッターを使用する必要がありますか?

回答:


8

私は以前、この種の哲学的な議論を私自身と持っていました。私はこれが意見に基づく答えであることを認識していますが、ここに私はほとんどの場合立ちます:

質問に答えるのに役立つと私が思う1つのことは、$ paramsを渡すことです。これは、設定された属性/配列メンバーを持っている場合と持っていない場合があります。

長年にわたって私はこの結論に達しました:

配列の受け渡しを避けます。

どうして?まあ、オプションの渡された引数に対してセンチネル値を設定または定義する方法はありません。

つまり、指定したコードでは、次のようなことはできません。

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1と$ arg2はオプションの引数です-渡されない場合、それぞれNULLとDEFAULT_VALがあります-明示的にチェックする必要はありません。

多分これは一種の恣意的なようです。

私はあなたが達成しようとしていることを理解していると思います-たくさんの議論とは対照的に単一の参照を渡すことです。これは私に私の次の結論をもたらします:

「アトミック」変数(文字列、整数、リテラル)を渡さない場合は、オブジェクトを渡します。

オブジェクトの受け渡しは参照によって行われるため、ここにはパフォーマンス上の利点があります(ただし、配列はPHP内でもほぼ同じだと思います)。

だからあなたは次のようなことをするかもしれません:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

渡されたオブジェクト引数は、デフォルト値自体を持っている可能性がありますが、「property1」、「property2」を持つことが保証されます。

さらに、ここではヒントを入力でき、優れたIDEはコード補完も正しく自動提案します。

しかし、鶏と卵の問題が発生していることにすぐに気づきます。ある時点で構築する必要がある、渡されたオブジェクト引数を使用してオブジェクトを構築しています。

これはどこに私たちを残すのでしょうか?まあ、私は結局、すべてのクラスがより良い用語がないために「アトミック」変数(文字列、浮動小数点数、倍精度浮動小数点数、整数、あなたが私のポイントを得るリソース)に蒸留し、私はしようとする傾向があるという結論に達しましたこれらの変数型またはオブジェクトを持つすべてのクラスを構築します-配列ではありません。

だから私はあなたの質問に答えましたか?おそらく正確ではない。しかし、私は多少様式的にではありますが、役に立つものを示してくれれば幸いです。コードは少しすっきりとして、読みやすく、コストも安いと思います。

さて、これはあなたの入力を無害化すべきではないと言っているのではありません。それは完全に別の議論です。

お役に立てれば。


1
これは良い点であり、IDEプロンプトには非常に便利ですが、オブジェクトのプロパティが多すぎてすべてをパラメーターとして渡すことができません。引数が7つあり、そのうちの5つがオプションであるとすると、最終的にnew object($param1,-some default value so I can specify the next parameter-, $param3);はデフォルト値がいくつかの異なる場所にハードコードされます
rgvcorley

3

配列をコンストラクターに渡さないようにする傾向がありますが、(構成ファイルから値を読み取るクラスの場合など)着信配列値を処理する必要がある場合があります。

このような場合、PHPの配列関数を利用して、自分が操作していると思うものを正確に操作できるようにします。

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

最後の行はarray_merge()、の値$defaultsをの対応する値で上書きするために使用します$incoming。またarray_intersect_key()、結果の配列に、クラス/メソッドが処理方法を知らない余分なキーが含まれていないことを確認するためにも使用します。


こんにちは、$ defaultsに単純な変数の代わりに配列が含まれている場合の動作はどうですか?
Pol Dellaiera 2014

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