我们应该直接访问受保护的属性还是使用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 ?
}
}
在示例中,我知道我无法直接访问/设置私有财产,并且它对公共财产无用。但我可以使用两种方式来保护受保护的财产。那么,有没有可以使用的标准?
答案 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 以及何时/如何修改它以及该类期望此属性遵循的规则,可能会直接触摸酒店。但是,如果您对该类的内部工作原理并不了解,并且只想与其公共接口进行交互以获得其结果,请使用访问器方法。