2012-11-16 57 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; 
}