我知道这可能是主观的,但我读过这个optimization page from Google for PHP他们建议直接使用变量属性而不需要 getter 和 setter。可以理解,我看到了这样做的性能提升,但这真的是一个值得遵循的好设计实践吗?
他们使用 getter/setter 的例子:
class dog {
public $name = '';
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$rover = new dog();
$rover->setName('rover');
echo $rover->getName();
建议的优化:
$rover = new dog();
$rover->name = 'rover';
echo $rover->name;
这对我的设计过程来说是一个可喜的变化,因为我看到需要取消 getters/setters,但是这样做还有哪些其他障碍/好处?
最佳答案
This would be a welcome change in my design process as I see the need for getters/setters going away, but what other hurdles/benefits might occur in doing this?
您无法在特定属性上实现特殊的获取/设置逻辑。对于标量属性(字符串、整数、 bool 值),这可能没有问题。但是,如果您有一个属性是延迟加载的类实例怎么办?
class Document
{
protected $_createdBy;
public function getCreatedBy()
{
if (is_integer($this->_createdBy)) {
$this->_createdBy = UserFactory::loadUserById($this->_createdBy);
}
return $this->_createdBy;
}
}
这个技巧只在方法中有效。你可以使用 __get
和 __set
来实现这个逻辑,但是当你添加属性时,你最终会得到一个大的讨厌的 switch()
block :
public function __get($name)
{
switch ($name) {
case 'createdBy':
// blah blah blah
case 'createdDate':
// more stuff
// more case statements until you scream
}
}
如果您只是想避免或推迟编写 getter 和 setter,请使用 __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 方法中保留特定于属性的逻辑使代码更易于维护。但是您不必在一开始就编写所有访问器方法,您可以轻松返回并添加它们,而无需重构所有其他代码。
问题是,您要优化什么?开发时间还是代码速度?如果您想优化代码速度,请确保在围绕瓶颈构建代码之前知道瓶颈在哪里。过早的优化是万恶之源。
关于php - 直接调用变量属性与 getter/setter - OOP 设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6215398/