我不是PHP开发人员,所以我想知道在PHP中使用显式getter/setter的优点和缺点是什么,在纯OOP风格中,带有私有字段(我喜欢的方式):
class MyClass {
private $firstField;
private $secondField;
public function getFirstField() {
return $this->firstField;
}
public function setFirstField($x) {
$this->firstField = $x;
}
public function getSecondField() {
return $this->secondField;
}
public function setSecondField($x) {
$this->secondField = $x;
}
}
或者只是公共字段:
class MyClass {
public $firstField;
public $secondField;
}
这篇文章不是专门关于__get和__set,而是关于__call,除了方法调用之外,它们是相同的思想。作为一种规则,我远离任何类型的允许重载的魔法方法,原因概述在评论和帖子中,然而,我最近遇到了一个第三方API,我使用了一个服务和一个子服务,例如:
http://3rdparty.api.com?service=APIService.doActionOne&apikey=12341234
这里重要的部分是,这个API除了子操作(在本例中为doActionOne)之外,其他内容都是相同的。这个想法是开发人员(我自己和其他使用这个类的人)可以通过名称调用子服务,而不是像这样:
$myClass->doAction(array('service'=>'doActionOne','args'=>$args));
我可以这样做:
$myClass->doActionOne($args);
对于硬编码来说,这只是大量的重复(这个例子非常类似于代码):
public function doActionOne($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
public function doActionTwo($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
public function doActionThree($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
protected function executeCoreCall($service)
{
$cURL = new \cURL();
return $cURL->('http://3rdparty.api.com?service='.$service.'&apikey='.$this->api.'&'.http_build_query($this->args))
->getResponse();
}
但是使用神奇的__call()方法,我能够使用动态方法访问所有服务:
public function __call($name, $arguments)
{
$this->args = $arguments;
$this->response = $this->executeCoreCall("APIService.{$name}");
return $this;
}
这种动态调用数据返回的好处是,如果供应商添加了另一个子服务,我不必向类中添加另一个方法或创建扩展类等。我不确定这是否对任何人都有用,但我想我会展示一个例子,其中__set, __get, __call等可能是一个考虑的选项,因为主要函数是数据的返回。
编辑:
巧合的是,我在帖子发布几天后看到了这篇文章,它准确地概述了我的场景。这不是我指的API,但方法的应用是相同的:
我是否正确使用api ?
除了这里已经很好的和受人尊敬的答案之外,我还想扩展一下没有setter /getter的PHP。
PHP没有getter和setter语法。正如Dave所指出的那样,它提供了子类或魔法方法来允许“挂钩”和覆盖属性查找过程。
魔术让我们这些懒惰的程序员在积极参与一个项目并熟悉它的时候,用更少的代码做更多的事情,但通常是以可读性为代价的。
在PHP中,由于强制使用类似getter/setter的代码架构而导致的每个不必要的函数,都会在调用时涉及自己的内存堆栈框架,并浪费CPU周期。
可读性:代码库会导致代码行膨胀,这会影响代码导航,因为更多的LOC意味着更多的滚动。
偏好:个人而言,作为我的经验法则,我接受静态代码分析的失败
作为避免走上这条神奇之路的标志,只要我当时没有明显的长期利益。
谬论:
一个常见的论点是可读性。例如,$someobject->width比$someobject->width()更容易读取。然而,与行星的周长或宽度可以假定为静态的不同,对象的实例(例如$someobject)需要一个width函数,可能需要测量对象的实例宽度。
因此,可读性的提高主要是因为确定的命名方案,而不是通过隐藏输出给定属性值的函数。
__get / __set使用:
属性值的预验证和预清理
字符串。
"
一些{mathsobj1->generatelatex}多
行文本{mathsobj1->latexoutput}
{mathsobj1->generatelatex}有很多变量
一些原因
"
在这种情况下,generatelatex将遵循actionname + methodname的命名方案
特殊的,明显的案例
dnastringobj - >同源框(one_rememberable_parameter美元)- >千钧一发——> findrelated ()
dnastringobj - >同源框(one_rememberable_parameter美元)- > gttccaatttga - > findrelated ()
注意:PHP选择不实现getter/setter语法。我并不是说getter /setter一般都不好。
这篇文章不是专门关于__get和__set,而是关于__call,除了方法调用之外,它们是相同的思想。作为一种规则,我远离任何类型的允许重载的魔法方法,原因概述在评论和帖子中,然而,我最近遇到了一个第三方API,我使用了一个服务和一个子服务,例如:
http://3rdparty.api.com?service=APIService.doActionOne&apikey=12341234
这里重要的部分是,这个API除了子操作(在本例中为doActionOne)之外,其他内容都是相同的。这个想法是开发人员(我自己和其他使用这个类的人)可以通过名称调用子服务,而不是像这样:
$myClass->doAction(array('service'=>'doActionOne','args'=>$args));
我可以这样做:
$myClass->doActionOne($args);
对于硬编码来说,这只是大量的重复(这个例子非常类似于代码):
public function doActionOne($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
public function doActionTwo($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
public function doActionThree($array)
{
$this->args = $array;
$name = __FUNCTION__;
$this->response = $this->executeCoreCall("APIService.{$name}");
}
protected function executeCoreCall($service)
{
$cURL = new \cURL();
return $cURL->('http://3rdparty.api.com?service='.$service.'&apikey='.$this->api.'&'.http_build_query($this->args))
->getResponse();
}
但是使用神奇的__call()方法,我能够使用动态方法访问所有服务:
public function __call($name, $arguments)
{
$this->args = $arguments;
$this->response = $this->executeCoreCall("APIService.{$name}");
return $this;
}
这种动态调用数据返回的好处是,如果供应商添加了另一个子服务,我不必向类中添加另一个方法或创建扩展类等。我不确定这是否对任何人都有用,但我想我会展示一个例子,其中__set, __get, __call等可能是一个考虑的选项,因为主要函数是数据的返回。
编辑:
巧合的是,我在帖子发布几天后看到了这篇文章,它准确地概述了我的场景。这不是我指的API,但方法的应用是相同的:
我是否正确使用api ?