Это было бы долгожданным изменением в моем процессе проектирования, поскольку я вижу необходимость в уходе геттеров/сеттеров, но какие еще препятствия/преимущества могут возникнуть при этом?
Вы теряете возможность реализовать специальную логику получения/установки для определенного свойства. Для свойств, которые являются скалярами (строки, целые числа, логические значения), возможно, это не проблема. Но что, если у вас есть свойство, представляющее собой экземпляр класса с отложенной загрузкой?
class Document
{
protected $_createdBy;
public function getCreatedBy()
{
if (is_integer($this->_createdBy)) {
$this->_createdBy = UserFactory::loadUserById($this->_createdBy);
}
return $this->_createdBy;
}
}
Этот трюк работает только в методе. Вы можете использовать __get
и __set
для этой логики, но когда вы добавляете свойства, вы получаете большой неприятный блок switch()
:
public function __get($name)
{
switch ($name) {
case 'createdBy':
// blah blah blah
case 'createdDate':
// more stuff
// more case statements until you scream
}
}
Если вы просто хотите избежать или отложить написание геттеров и сеттеров, используйте магический метод __call
для перехвата вызовов методов, которые следуют соглашению об именах getProperty()
и setProperty()
. Вы можете поместить всю логику получения/установки по умолчанию в __call
и больше никогда к ней не прикасаться:
abstract class Object
{
public function __call($method, $args)
{
$key = '_' . strtolower(substr($method, 3, 1)) . substr($method, 4);
$value = isset($args[0]) ? $args[0] : null;
switch (substr($method, 0, 3)) {
case 'get':
if (property_exists($this, $key)) {
return $this->$key;
}
break;
case 'set':
if (property_exists($this, $key)) {
$this->$key = $value;
return $this;
}
break;
case 'has':
return property_exists($this, $key);
break;
}
throw new Exception('Method "' . $method . '" does not exist and was not trapped in __call()');
}
}
Этот подход очень быстр с точки зрения разработки, потому что вы можете просто расширить класс Object, определить некоторые свойства, и вы готовы к гонкам:
class Foo extends Object
{
protected $_bar = 12345;
}
$foo = new Foo();
echo $foo->getBar(); // outputs '12345'
$foo->setBar(67890); // next call to getBar() returns 67890
$foo->getBaz(); // oops! 'baz' doesn't exist, exception for you
Это медленно с точки зрения выполнения, потому что магические методы чертовски медленны, но вы можете смягчить это позже, определив явные методы getBar()
и setBar()
(поскольку __call
вызывается только при вызове метода, который не определен) . Но если к определенному свойству обращаются не очень часто, возможно, вас не волнует, насколько оно медленное. Дело в том, что позже легко добавить специальные методы get/set, и остальная часть вашего кода никогда не заметит разницы.
Я позаимствовал этот подход у Magento и считаю его очень удобным для разработчиков. Генерация исключения при вызове get/set для несуществующего свойства помогает избежать фантомных ошибок, вызванных опечатками. Сохранение логики свойств в собственных методах get/set упрощает поддержку кода. Но вам не нужно писать все методы доступа в начале, вы можете легко вернуться и добавить их без рефакторинга всего остального кода.
Вопрос в том, что вы пытаетесь оптимизировать? Время разработки или скорость кода? Если вы хотите оптимизировать скорость кода, убедитесь, что вы знаете, где находятся ваши узкие места, прежде чем создавать свой код вокруг них. Преждевременная оптимизация — корень всех зол.
person
squirrel
schedule
02.06.2011
$x = ...; echo $x
использует вдвое больше памяти, чемecho ...;
напрямую. - person NikiC   schedule 02.06.2011