2011-12-19 22 views
16

私はクラス間でいくつかの「セッター」メソッドを用意していますが、便宜上、参照で引数をとり、新しい値に置き換える前に既存の値を設定するオプションのパラメータ$previousを追加しました。 1。例:PHPのオプション引数のテスト

public function set_value($key, $value, &$previous = null) 
{ 
    $previous = $this->get_value($key); 
    $this->_values[$key] = $value; 
    return $this; 
} 

これは正常です。しかし、状況によっては、対応する「ゲッター」メソッドが少しプロセス集中的で、無条件で実行することは無駄です。

if(null !== $previous) 
{ 
    $previous = $this->get_value($key); 
} 

これはしかし動作しない、できるだけ頻繁$previousの引数として渡された変数は以前にそれは適用範囲だし、デフォルトとにかくnullにして定義されていない:私は、私がテストすることができ考え出し。私がハッキングた唯一の解決策は以下のとおりです。

if(array_key_exists(2, func_get_args())) 
{ 
    // ... 
} 

私は、引数のインデックスに依存しているメソッド本体を好きではない(それを:それは1行に

public function set_value($key, $value, &$previous = null) 
{ 
    $args = func_get_args(); 
    if(isset($args[2]) 
    { 
     $previous = $this->get_value($key); 
    } 
    $this->_values[$key] = $value; 
    return $this; 
} 

あるいは、不要だと思われます。)私はここで何を達成するためのよりクリーンな方法がありますか?


私が試してみた:

if(isset($previous)){} 

if(!empty($previous)){} 

if(null !== $previous){} 

どちらも仕事を。

考えられる解決策これまで:

if(func_num_args() == $num_params){} 

if(array_key_exists($param_index, func_get_args())){} 

// 5.4 
if(isset(func_get_args()[$param_index])){} 

// 5.4 
if(func_num_args() == (new \ReflectionMethod(__CLASS__, __FUNCTION__)) 
    ->getNumberOfParameters()){} 

@DaveRandom - の分野におけるだから、何か:

define('_NOPARAM', '_NOPARAM' . hash('sha4096', microtime())); 

function foo($bar = _NOPARAM) 
{ 
    // ... 
} 

@hoppa - ユースケース:

$obj->set_something('some_key', $some_value, $previous) // set 
    ->do_something_that_uses_some_key() 
    ->set_something('some_key', $previous) // and reset 
    ->do_something_that_uses_some_key() 
    -> ... 

の代わりに:上記のコメント/議論から抽出

$previous = $obj->get_something('some_key'); // get 
$obj->set_something('some_key', $some_value) // set 
    ->do_something_that_uses_some_key(); 
    ->set_something($previous) // and reset 
    ->do_something_that_uses_some_key(); 
    -> ... 
+3

の削除デフォルト値は、あなたが 'false'を(または「いくつかの値として' $のprevious'のデフォルト値を定義することができませんでした間違った "型) - それは渡された' null'であることを知っていますが、 'FALSE'(または何でも)ではありません。このメソッドにも穴があります(ユーザーがデフォルト値を渡す可能性があります)が、まともなアプローチになると思います。特に、デフォルト値に、渡された変数にない可能性が高い長いランダムな文字列を作成すると。 – DaveRandom

+0

@DaveRandom - 状況によっては、前の値がブール値「false」になる可能性があります。私はそれが意味の意図であるために「ヌル」を選んだ、「価値の欠如」。 – Dan

+0

長いランダムな文字列について編集したコメントを参照してください - それは美しいまたは完璧なアプローチではないと認めますが、それは作品99.99999%のアプローチです... – DaveRandom

答えて

3

ないが、これは、私はそれを実装する方法を次のとおりです。

public function set_value($key, $value) 
{ 
    $this->_values[$key] = $value; 
    return $this; 
} 
public function set_get_value($key, $value, &$previous) 
{ 
    $previous = $this->get_value($key); 
    $this->_values[$key] = $value; 
    return $this; 
} 

ユースケース例:

$obj->set_get_something('some_key', $some_value, $previous) // set AND get 
    ->do_something_that_uses_some_key() 
    ->set_something('some_key', $previous) // and reset 
    ->do_something_that_uses_some_key() 
    -> ... 

他の機能を使う理由

このソリューションは、いくつかの利点があります:

  1. 名である他のコーダー
  2. は、(未定義の)変数がすでに持ってあなたの問題を解決していない隠れた副作用のために、より明示的に、より少ない混乱値
  3. func_num_argsを呼び出すのオーバーヘッドなし、または他のいくつかの「メタ」機能

EDIT:コードを入力してください。

EDIT 2:& $前回set_get_value()関数(draevorのおかげ)

+0

良い代替手段。小さな修正 - '&$ previous'は2番目の関数のデフォルト値を持つ必要はありません。それはそこにあることを意味します。 – deviousdodo

+0

本当に:)編集済み! – catchmeifyoutry

1

:引数が渡されたかどうかを確認するために

あなたは2つのオプションを持っている - あなたと(値に対する引数の値をチェックしますnullで終わったか)、引数の数を確認してください。

最初のオプションを使用すると、関数の外から渡すことのできない値はありません。したがって、常に偽陽性の可能性があります(現在はnullと同じことが起こっています)。しかし、DaveRandomのランダムな文字列を使った例では、ほとんどの場合十分ですが、私はそれを過度のものと見ています。

私は第2の選択肢が最もクリーンである(速い、可読な、など)と思います。すでにfunc_get_argsで行っていたことを少し改善して、func_num_argsを使用します。この方法で、引数インデックスではなく、渡された引数の数をチェックします。

あなたはあなたの問題(テスト何とかオプションの引数を)解決したかったか、おそらく
+0

ありがとう@draevor - "*私は試した/可能な解決策*"の下で私の編集をチェックしてください。最後のもの(*は一度5.4になる*)は、 $ previous'パラメータは常にlastです。私が前に言ったように、あなたの答えは間違いなく最高の候補です。私はこれをちょっと座らせて、木工から何も出てこなければあなたの印をつけます。 – Dan

関連する問題