Это было бы желанным изменением в моем процессе проектирования, так как я вижу необходимость ухода геттеров / сеттеров, но какие другие препятствия / преимущества могут возникнуть при этом?
Выпотерять способность реализовывать специальную логику get / set для определенного свойства.Для свойств, которые являются скалярами (строки, целые числа, логические значения), возможно, это не проблема.Но что, если у вас есть свойство, которое является экземпляром класса с отложенной загрузкой?
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()
.Вы можете поместить всю логику get / set по умолчанию в __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()');
}
}
Этот подход очень быстр с точки зрения development , потому что вы можете просто расширитьКласс объекта, определите некоторые свойства, и вы приступите к гонкам:
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 облегчает поддержку кода.Но вам не нужно писать все методы доступа с самого начала, вы можете легко вернуться и добавить их без рефакторинга всего вашего другого кода.
Вопрос в том, что вы пытаетесь оптимизировать?Время разработчика или скорость кода?Если вы хотите оптимизировать скорость кода, убедитесь, что вы знаете, где находятся ваши узкие места, прежде чем строить свой код вокруг них.Преждевременная оптимизация - корень всего зла.