我们应该直接访问受保护的属性还是使用getter?

时间:2016-02-17 14:14:42

标签: php

我们应该直接访问受保护的属性还是使用PHP中的getter来访问?

我有两个班,一个是另一个班的女儿。在母亲中,我将某些属性声明为受保护,并为我的属性生成所有getter。因此,我可以直接或通过getter访问和定义这些属性,但我不知道是否有更好的解决方案。

示例:

class Mother {

    private $privateProperty;
    protected $protectedProperty;
    public $publicProperty;

    /*** Private property accessors ***/   

    public function setPrivateProperty($value)
    {
        $this->privateProperty = $value;
    }

    public function getPrivateProperty()
    {
        return $this->privateProperty;
    }

    /*** Protected property accessors ***/   

    public function setProtectedProperty($value)
    {
        $this->protectedProperty = $value;
    }

    public function getProtectedProperty()
    {
        return $this->protectedProperty;
    }
}

class Child extends Mother {

    public function showProtectedProperty() {
        return $this->getProtectedProperty();   // This way ?
        return $this->protectedProperty;        // Or this way ?
    }

    public function defineProtectedProperty() {
        $this->setProtectedProperty('value');   // This way ?
        $this->protectedProperty = 'value';     // Or this way ?
    }
}

在示例中,我知道我无法直接访问/设置私有财产,并且它对公共财产无用。但我可以使用两种方式来保护受保护的财产。那么,有没有可以使用的标准?

3 个答案:

答案 0 :(得分:4)

当您确实在类层次结构中使用getter和setter时,可以实现最佳封装。这意味着:属性应该是私有的,getter / setter是受保护的(如果不是公共的)。

例如,如果要记录对某些属性的访问权限,想要添加过滤器方法或其他检查,则只要在派生类中访问这些属性,就会删除整个机制。

(当然,在某些情况下,您只需将属性公开以使代码更短,因为您知道该类实际上只是数据持有者......但是,在这种情况下,这些属性仍然不会保护,但只是公开)

答案 1 :(得分:3)

我在Programmers.SE上回答了一个类似的问题:

  

我不会说哪个好或坏,因为这部分取决于你的情况(在我看来)。但是考虑到你的getter和setter可能会在以后更改实现,绕过它们会跳过这个逻辑。

     

例如,如果添加"脏"会发生什么?以后标记到某些setter字段?通过在内部代码中调用setter,您可以在不更改任何其他代码的情况下设置脏标志。在许多情况下,这将是一件好事。

您可能需要特殊规则,例如初始化代码可能会跳过使用setter。最重要的是在项目中选择适当的策略并坚持一致。

答案 2 :(得分:3)

您甚至不应该将属性视为具有“getter / setter”。这两个是不同的东西。属性存储状态,getters返回值,setter修改对象状态。有时这些可能具有非常直接的1:1相关性,但它们不需要。

事实上,如果您的所有setter都是$this->foo = $foo且getter执行return $this->foo,那么会使其成为public属性!对于所有意图它已经是目的了。有功能打扮这个属性是没有意义的,它们实际上并没有增加任何价值。

为了讨论,想象一下这样的课:

class Foo {

    protected $timestamp;

    public function setStartTime($int) {
        $this->timestamp = new DateTime("@$int");
    }

    public function getElapsedTime() {
        return $this->timestamp->diff(new DateTime);
    }

}

这更清楚地说明了状态状态修改值返回之间的脱节。 “setter”接受一个整数,该属性存储DateTime对象,“getter”返回DateInterval个对象。他们彼此之间没有任何关系。

将此问题重新解决原始问题:如果您知道该属性代表什么 state 以及何时/如何修改它以及该类期望此属性遵循的规则,可能会直接触摸酒店。但是,如果您对该类的内部工作原理并不了解,并且只想与其公共接口进行交互以获得其结果,请使用访问器方法。