独立的getter/setter方法,或组合


Independent getter/setter methods, or combined?

在做一个项目的时候,我一直在做一些改变,并浏览现有的框架API文档。

在阅读Kohana文档时,我注意到任何给定类的getter/setter通常是组合在一起的:

public function someProperty($value = null){
    if(is_null($value){
        return $this->_someProperty;
    }
    $this->_someProperty = $value;
    return $this;
}

而不是:

public function setSomeProperty($value){
    $this->_someProperty = $value;
    return $this;
}
public function getSomeProperty(){
    return $this->_someProperty;
}

除了减少给定类的方法计数之外,这样做(前者)还有什么价值吗?我一直认为方法(通常是函数)应该更能描述操作。当其他有经验的开发者看到这种情况时,他们会畏缩吗?

我只是惊讶地看到一个流行的框架使用这样的约定(我当然没有使用过Kohana )

我认为这是不好的做法,因为它违反了CommandQuerySeparation。设置值就是改变状态(命令)。获取值就是请求状态(查询)。一个方法不应该同时做两件事,而应该只做一件事。

另外,当一个方法只叫username时,它做什么并不明显,例如没有动词,比如get或set。这在你的例子中变得更糟,因为返回值要么是对象本身,要么是属性值,所以它不一致。

此外,getter(和setter)应该谨慎使用,因为它们会很快使你的API混乱。你拥有的getter和setter越多,这个对象的合作者就需要更多关于这个对象的知识。如果您发现您的对象向其他对象询问它们的内部结构,那么很可能是您放错了责任。

jQuery的方法与Kohana相同。然而,我认为最好为设置和获取创建单独的方法。这个方法的作用更明显我认为它在代码补全中更实用。例如,你输入set,你会得到一个你可以设置的所有属性的列表。

另一个缺点是:如果您想将值设置为null怎么办?这将不起作用,因为null是返回值的标识符,您在设置特定值时受到限制…

所以这很好,因为你必须写得更少,但是嘿,在你的方法前面有三个字母(set/get)是什么?

尽管Kohana在OOP中使用了如此不寻常的技术,但我认为您首先应该遵循编码惯例。当然,最好对类中的每个属性使用单独的getter和setter。所以,如果有可能在不打破惯例的情况下使用它们——就这么做吧,你不会错的;)。如果您对使用某些OOP技术有疑问,您也可以在这里阅读关于PHP OOP的良好习惯- http://www.ibm.com/developerworks/opensource/library/os-php-7oohabits/。希望能有所帮助:)

我宁愿相信他们这样做有一个合理的解释。例如,为了更容易实现ArrayAccess。唯一确定的方法就是直接问他们。

回答你的问题,是的,当我看到第一种方法时,我会畏缩。违背了面向对象原则。

为什么不这样做呢?

public function someProperty($value = null)
{
    if (func_num_args() === 1) {
        $this->someProperty = $value;
        return $this;
    } else {
        return $this->someProperty;
    }
}

我认为这是实现getter/setter组合的唯一正确方法

如果你在任何地方都这样做,这是一个好方法,但它真的需要所有,也许这个框架的程序员已经习惯了,(有点像jquery)

然而这会让我困惑

对于设置和获取我总是使用setter和getter:

   public function __set($key, $value) {
      // assign value $value to $this->key
   }
   public function __get($key) {
      // return value of this->key
   }

为了便于讨论,

组合方法确实提供了一些好处:

  1. 避免__get__set魔法,同时仍然模拟公共属性。(无论如何,我不建议在这些情况下使用magic)
  2. 使用thing()比使用getThing() setThing()更简洁。
  3. 即使方法将做更多,它们仍然可以被认为是"做一个thing()",即处理thing()。属性也不止做一件事。它们允许你设置和获取值。
  4. 有人认为thing()没有给出动词。然而,我们可以假设没有动词的thing()意味着我们像使用属性一样使用它(我们获取设置它)。对于接口,我们可以说不带参数的thing()只读,带参数的thing($arg)读/写。我们为什么要羞于采用这种方法呢?在某种程度上,我们采用了添加getter setter 的想法,不是吗?
  5. 如果您正在使用基于web的语言(如PHP),那么您可能也会使用jQuery。JQuery已经在做这种thing()了,而且效果很好。
  6. 如前所述,使用func_num_args()有助于完美地实现此方法。

就我个人而言,我已经在我目前的应用程序中承担了很大一部分风险,所以我可能会使用旧的久经考验的getter和setter(参见Jimmy Bogard关于数据操作的getter/setter的文章"寻找平衡"部分)。我想我们已经训练过寻找这些get/set前缀(以及我们的IDE),以查看我们可以在类中使用哪些属性。这是一个我愿意在某个时候回到的讨论。