对于我的设计流程来说,这会是一个受欢迎的变化,因为我看到了getter/setter的需求正在减少,但是如果这样做,可能会出现哪些其他障碍/好处呢?
您将失去在特定属性上实现特殊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':
case 'createdDate':
}
}
如果你只是想避免或推迟编写getter和setter方法,可以使用__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()');
}
}
从开发的角度来看,这种方法非常快速,因为您可以扩展Object类,定义一些属性,然后就可以开始编程了:
class Foo extends Object
{
protected $_bar = 12345;
}
$foo = new Foo();
echo $foo->getBar();
$foo->setBar(67890);
$foo->getBaz();
从执行效率来看,使用魔术方法会导致速度变慢,但您可以通过定义显式的getBar()和setBar()方法来缓解这个问题(因为__call只有在调用未定义的方法时才会被调用)。但是如果某个属性很少被访问,也许您并不关心它的速度。重要的是,稍后添加特殊的get/set方法非常容易,而其他代码则毫不知情。
我从Magento中借鉴了这种方法,并发现它非常适合开发人员使用。当调用不存在的属性的get/set时抛出异常可以帮助您避免因打字错误而导致的虚假错误。将特定于属性的逻辑保留在其自己的get/set方法中可以使代码更易于维护。但是您不必一开始就编写所有的访问器方法,您可以轻松地返回并添加它们而无需重构所有其他代码。
问题是,您想要优化什么?开发人员时间还是代码速度?如果您想要优化代码速度,请确保在围绕它们构建代码之前知道瓶颈在哪里。过早的优化是万恶之源。
$x = ...; echo $x
使用的内存是直接使用echo ...;
的两倍。 - NikiC