php - 直接调用变量属性与 getter/setter - OOP 设计

标签 php optimization variables getter-setter design-principles

我知道这可能是主观的,但我读过这个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/

相关文章:

java - 视频图像处理,我该怎么做?

c# - 异步 HttpWebRequest 上的此 .net/C# 代码的 PHP 等效项、自定义 header 二进制有效负载和分析响应

javascript - 即使在函数中更新后,全局对象仍未定义

javascript - 使用 JavaScript 增加局部变量

CSS calc() 与多个单位相乘

php - Paypal - 如何减少经常性付款资料金额

PHP - Laravel 集合或数组的类型提示

python - 优化 Python 代码

hibernate - 如何优化在 Hibernate 中获取多个集合?

缓存友好矩阵移位函数