Динамически добавлять частное свойство к объекту

У меня есть класс:

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 чтобы сделать переменные закрытыми?

Редактировать Использование частного массива – это еще один способ и, безусловно, не мой ответ.

Просто простой, плохой дизайн.

Какова цель добавления частного [!] Поля во время выполнения? Существующие методы не могут полагаться на такие добавленные поля, и вы будете возиться с функциональными возможностями объекта.

Если вы хотите, чтобы ваш объект вел себя как hashmap [т.е. вы можете просто вызвать $obj -> newField = $newValue ], подумайте об использовании магических методов __get и __set .

Вы могли бы сделать что-то подобное.

Функция __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]; } } } 

Я бы работал со всем массивом:

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

Тогда у вас есть больше вариантов, когда вам нужны другие значения, и вы можете выполнять итерацию по массиву и работать с ними. Когда у вас есть единственная переменная, в большинстве случаев ее бит завершается.

Вот подход, основанный на доступе:

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