1

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

function __construct($params) {

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

}

一部のデフォルト値は他のプロパティから取得されるため、コンストラクターでこれを行っていました。しかし、代わりにセッターで行うことができると思います。

この方法の長所と短所は何ですか。また、より良い方法はありますか?

編集:プロパティが配列で提供されていない場合、値は別のプロパティから取得されるといういくつかの依存関係がありますが$params、その他のプロパティはオプションであり、デフォルト値を持つ可能性があるため、プロパティが初期化される順序が重要です。

これは、ゲッターとセッターを使用した場合、依存関係がコンストラクターではなくゲッターで抽象化されるため、それらを呼び出す順序が明らかではないことを意味します...

4

3 に答える 3

1

正しいデータ型と検証をアサートする(そして前述のデフォルト値ロジックを含む)適切なゲッター/セッター関数を作成することをお勧めします。これらはコンストラクター内で使用する必要があります。相互に依存する複数のフィールドを設定する場合、この複雑なデータ用に個別のセッターがあると便利なようです。とにかく彼らはどのような方法で依存していますか?

例えば:

// META-Config
protected $static_default_values = array(
  "price" => 0.0,
  "title" => "foobar"
  // and so on
);

protected $fallback_getter = array(
  "price" => "getfallback_price"
);


// Class Logic
public function __construct($params){
  $this->set_properties($params);
}

public set_properties($properties){
  // determines the sequence of the setter-calls
  $high_prio_fields = array("price", "title", "unimportant_field");

  foreach($high_prio_fields as $field){
    $this->generic_set($field, $properties[$field]);
    // important: unset fields in properties-param to avoid multiple calls
    unset($properties[$field]);
  }

  foreach($properties as $field => $value){
    $this->generic_set($field, $value);
  }
}

// this could also be defined within the magic-setter,
// but be aware, that magic-functions can't be resolved by your IDE completely
// for code-completion!
private function generic_set($field, $value){
  // check if setter exists for given field-key
   $setter_func = "set_".$v;
   if(method_exists($this, $setter_func){
     call_user_func_array(array($this, $setter_func), array($v));
   }
   // else => just discard  :)        
}

// same comment as generic-set
private function generic_get($field){
  // check if value is present in properties array
  if(isset($this->properties[$field]){
    return $this->properties[$field];
  }

  // check if fallback_getter is present
  if(isset($this->fallback_getter[$field]){
    return  call_user_func_array(array($this, $this->fallback_getter[$field]));
  }

  // check for default-value in meta-config
  if(isset($this->static_default_values[$field]){
    return $this->static_default_values[$field];
  }

  // else => fail (throw exception or return NULL)
  return null;
}


public function get_price(){
  // custom getter, which ovverrides generic get (if you want to)
  // custom code...
  return $this->generic_get("price");
}

private function getfallback_price(){
  return $this->properties["other_value"] * $this->properties["and_another_value"];
}

public function set_price($price){
  $price = (float) $price; // convert to correct data-type
  if($price >= 0.0){
    $this->properties["price"] = $price;
  }
  // else discard setting-func, because given parameter seems to be invalid
  // optional: throw exception or return FALSE on fail (so you can handle this on your own later)
}

編集内容を更新します。 変更されたソースコードは、すべての要求を解決する必要があります(setter-funcsの順序、get-valueのさまざまな解決)。

于 2012-04-07T10:21:52.807 に答える
0

多くのデフォルトオプションがあり、それらを上書きできるようにする必要がある場合-以前にjQueryを使用して見たことがある.extend()ように-私はこのシンプルで迅速な方法を使用するのが好きです:

class Foo {
    private $options;

    public function __construct($override = array()) {
        $defaults = array(
           'param1' => 'foo', 
           'param2' => ..., 
           'paramN' => 'someOtherDefaultValue');
        $this->options= array_replace_recursive($defaults, $override);
    }
}     

特にクラスを開始する場合、これは非常に簡単で柔軟な方法ですが、すでに述べたように、そのコードが頻繁に使用される場合は、特に getter と setter を使用してこれらのオプションをさらに制御することを導入することはおそらく悪い考えではありません。問題を正しく理解した場合の依存関係のように、これらのオプションの一部が取得または設定されたときにアクションを実行する必要がある場合。

また、getter と setter を自分で実装する必要がないことにも注意してください。PHP では、__get と __set マジック メソッドを使用できます。

それは、うまくいけばいくつかのアイデアを与えるいくつかの役に立たないコードに従います。

[...inside Foo...]
public function __set($key, $value){
    switch(true){
        //option exists in this class
        case isset($this->options[$key]):
           //below check if $value is callable
           //and use those functions as "setter" handlers
           //they could resolve dependencies for example 
           $this->options[$key] = is_callable($value) ? $value($key) : $value;  
        break;
        //Adds a virtual setter to Foo. This so called 'magic' __set method is also called if the property doesn't exist in the class, so you can add arbitrary things.
        case $key === 'someVirtualSetterProp': Xyzzy::Noop($value); break;
        default: 
           try{ parent::__set($key, $value); } catch(Exception $e){ /* Oops, fix it! */ }
    }
}

上記の例では、さまざまなアプローチで絞り込んでおり、通常、それらをそのように混在させることは意味がないことに注意してください。これは、いくつかのアイデアを説明するためだけに行ったものであり、ニーズに合ったものをより適切に決定できることを願っています.

于 2012-04-07T11:11:24.120 に答える
0

「グローバルに利用可能な」関数を作成しますarray_get

public static function array_get($array, $property, $default_value = null) {
    return isset($array[$property]) ? $array[$property] : $default_value;
}
于 2012-04-07T10:17:36.267 に答える