2012-11-16 58 views
3

我有一個類:動態私有屬性添加到對象

class Foo { 
    // Accept an assoc array and appends its indexes to the object as property 
    public function extend($values){ 
     foreach($values as $var=>$value){ 
      if(!isset($this->$var)) 
       $this->$var = $value; 
     } 
    } 
} 

$Foo = new Foo; 
$Foo->extend(array('name' => 'Bee')); 

現在$Foo對象具有公共屬性name與價值Bee

如何更改extend函數使變量爲私有?使用私有數組是另一種方式,絕對不是我的答案。

+0

你爲什麼不存儲整個陣列成私有財產? – Carlos

+2

$ i和$ var不應該是同一個變量嗎? –

+0

@Lewyx:是的,只是一個錯誤而編輯。 – Omid

回答

3

簡單而不好的設計。

在運行時添加私有[!]字段的目的是什麼?現有的方法不能依賴這些添加的字段,並且你會搞亂對象功能。

如果你希望你的對象的行爲像一個哈希映射[即你可以撥打$obj -> newField = $newValue],考慮使用魔術__get__set方法。

+1

實際上,這將是創建不可變對象的好方法。它會像一個常量集合。但是對於key => val的好處,值可能是標量,[],{} ... – CoR

3

你可以做這樣的事情。

__get函數將檢查給定密鑰是否在 私有屬性中設置。

class Foo { 

private $data = array(); 

// Accept an array and appends its indexes to the object as property 
public function extend($values){ 
    foreach($values as $i=>$v){ 
     if(!isset($this->$i)) 
      $this->data[$i] = $v; 
    } 
} 

public function __get($key) { 
    if (isset($this->data[$key])) { 
     return $this->data[$key]; 
    } 
} 

} 
+0

這是一種替代方法,而不是我的回答 – Omid

0

我將與整個陣列的工作:

$Foo = new Foo; 
$Foo->setOptions(array('name' => 'Bee')); 

class Foo { 
    private $options = array(); 

    public function setOptions(array $options) { 
     $this->options = $options; 
    } 

    public function getOption($value = false) { 
     if($value) { 
      return $this->options[$value];  
     } else { 
      return $this->options; 
     } 
    } 
} 

那麼你有更多的選擇,當你需要其他的值,你可以通過數組進行迭代,並與他們合作。當你在大多數情況下有單變量時,它有點複雜。

0

這裏是一個訪問爲基礎的方法:

class Extendible 
{ 
    private $properties; 

    public function extend(array $properties) 
    { 
     foreach ($properties as $name => $value) { 
      $this->properties[$name] = $value; 
     } 
    } 

    public function __call($method, $parameters) 
    { 
     $accessor = substr($method, 0, 3); 
     $property = lcfirst(substr($method, 3)); 
     if (($accessor !== 'get' && $accessor !== 'set') 
       || !isset($this->properties[$property])) { 
      throw new Exception('No such method!'); 
     } 
     switch ($accessor) { 
      case 'get': 
       return $this->getProperty($property); 
       break; 
      case 'set': 
       return $this->setProperty($property, $parameters[0]); 
       break; 
     } 
    } 

    private function getProperty($name) 
    { 
     return $this->properties[$name]; 
    } 

    private function setProperty($name, $value) 
    { 
     $this->properties[$name] = $value; 
     return $this; 
    } 
} 

演示:

try { 
    $x = new Extendible(); 
    $x->extend(array('foo' => 'bar')); 
    echo $x->getFoo(), PHP_EOL; // Shows 'bar' 
    $x->setFoo('baz'); 
    echo $x->getFoo(), PHP_EOL; // Shows 'baz' 
    echo $x->getQuux(), PHP_EOL; // Throws Exception 
} catch (Exception $e) { 
    echo 'Error: ', $e->getMessage(), PHP_EOL; 
}