使用__get / __ set而不是传统的getter / setter方法有什么好处,除了少量代码?

时间:2011-07-17 15:35:30

标签: php get set magic-methods

来自Java,我只有几次假期访问PHP。看看魔法获取和设置方法,我(受Java影响)的肚子开始受到伤害:看起来好像是直接访问属性(当然,你实际上是在使用__get和__set)。

所以 - 除了你必须编写的代码少之外,使用magic getter和setter方法而不是传统的getX()/ setX()方法有什么好处吗?我应该在编写PHP时开始使用它们吗?

谢谢,最好!

7 个答案:

答案 0 :(得分:2)

__get()的唯一好处是可以减少代码,但即便如此,情况也不一定如此。例如,如果您有一组10个私有成员,并且您希望getter显示5,那么您必须编写__get(),以便在调用其中一个伪可见成员时发送它。否则,您要么发出错误(否则会在没有__get()的情况下自然发生错误,或者返回可能实际上没有帮助的null等值。

我必须谴责任何建议一般使用吸气剂和制定者的人。这通常表明架构存在问题。解释以下两个代码块之间的概念差异,例如:

class _ {
   public $_;
}

VS

class _ {
   private $_;
   public function get_() {
      return $this->_;
   }
}

没有区别。

但是,正如许多人会指出使用getter的优势在于,这允许您以某种方式透明地修改返回值,以使其对收件人有用。但是,我们回到架构问题。您根本不应该出于任何原因公开类的内容。相反,您应该告诉班级执行一个动作(可能会根据其状态而有所不同)。使用getter通常可以根据查看的状态查询类的状态并在外部执行操作。

我对__set()和setter基本上有相同的论点,但__set()允许你做一件好事:

class _ {
   private $_ = array();
   public function __set($key, $val) {
      $this->_[$key] = $val;
   }
}

这可以让您输入非常好的$_obj->key = 'val'。请注意,与此没有太大区别,并添加另一个方法,例如add(),它接受​​键和值并执行相同的操作,我只是更喜欢对象设置符号。

答案 1 :(得分:1)

__get____set__完全是动态的。因此,例如,如果调用它们以启用延迟加载,则可以启动数据库请求。当然,你也可以使用getter和setter来做到这一点,但是你每次都必须这样做。您也可以执行类似AOP的操作,因为每个属性调用都通过一个方法传递。总而言之,__get__/__set__提供了更多的灵活性,以及​​他们处理的时间。你可以用它做真正的高级/酷炫的东西。

答案 2 :(得分:1)

优点是,当您进行重构时,可以处理直接分配/读取而无需立即更改完整的代码库,代码可能会更短,并且人们可以更轻松地创建字符串(例如: $title="<title>{$obj->title}</title>";$title='<title>'.$obj->getTitle().'</title>';

然而,__get&amp; __set方法可能会很快变得庞大而且难以处理,并且在正确编码时明确地说,我认为使用显式set/getX()方法更好地调用明确的函数,并且代码详细程度的微小增加是我认为合理的,因为人们可以很容易地看到实际调用函数的内容什么不是。可能的异常可能是你为另一个类/对象构建一个装饰器,但那就是它。

答案 3 :(得分:1)

getter和setter方法以及__set()__get()方法之间几乎没有区别!这些都是神奇的方法! 当您想要将未定义状态分配给对象时使用__set(),因此__get()也用于获取未定义状态的值! setter和getter用于分配或获取已定义状态的值

答案 4 :(得分:0)

  

除了你必须编写的代码少,使用magic getter和setter&gt;方法而不是传统的getX()/ setX()方法有什么好处吗?我应该在编写PHP时开始使用它们吗?

鉴于编写代码的代码较少,已经是开始使用它们的有力理由 另一个原因是你可以为你的所有getter / setter添加一个共同的行为

function __set() {
   //> Do some code in common between all setter

   //> set your var here
}

答案 5 :(得分:0)

为每个属性编写getX()/ setX()时,实际上,您至少需要7行代码。这假设您的开始方法大括号与定义位于同一行,并且您只将一行代码放入方法中,然后您将自己的大括号放在自己的行上。

对于一个非平凡的对象,将其乘以6(YMMV)。这是42行仅用于属性访问/变异。那包括输入验证或规范化。如有其他选择,请查看:https://github.com/metaphp/attributes

答案 6 :(得分:0)

动态编程存在开销(例如使用魔术方法)。旧基准:Benchmarking magic

由于PHP是一种动态(而不是完全企业)语言,在许多情况下(减少代码行并且缺少一些纳秒)似乎是个好主意(用于调试,可伸缩性,减少错误等。)