Dynamically add a private property to an object

匿名 (未验证) 提交于 2019-12-03 02:31:01

问题:

I have a class:

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')); 

Now the $Foo object has a public name property with value Bee.

How to change extend function to make variables private ?

Edit Using a private array is another way and definitely not my answer.

回答1:

Just plain, bad design.

What's the purpose of adding a private [!] field at runtime? Existent methods can't rely on such added fields, and you'd be messing with the object functionality.

If you want your object to behave like an hashmap [i.e. you can just call $obj -> newField = $newValue], consider using magic __get and __set methods.



回答2:

You could do something like this.

The __get function will check if the given key is set inside the private property.

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];     } }  } 


回答3:

I would work with the whole array:

$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;         }     } } 

Then you have more options when you need other values and you can iterate through the array and work with them. When you have single variable in most cases its a bit complecated.



回答4:

Here is an accessor based approach:

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;     } } 

Demo:

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; } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!