我不是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;
}

当前回答

一般来说,第一种方法总体上更受欢迎,因为具有编程知识的人可以轻松地转换到PHP,并以面向对象的方式完成工作。第一种方法更为普遍。我的建议是坚持使用在许多语言中都行之有效的方法。然后,当你使用另一种语言时,你将准备好完成一些事情(而不是花时间重新发明轮子)。

其他回答

封装在任何面向对象语言中都很重要,与受欢迎程度无关。在动态类型语言(如PHP)中,它特别有用,因为如果不使用设置符,几乎没有办法确保属性是特定类型的。

在PHP中,这是有效的:

class Foo {
   public $bar; // should be an integer
}
$foo = new Foo;
$foo->bar = "string";

在Java中,它没有:

class Foo {
   public int bar;
}
Foo myFoo = new Foo();
myFoo.bar = "string"; // error

使用魔法方法(__get和__set)也可以,但只有当访问的属性的可见性低于当前作用域可以访问的时候。如果使用不当,调试时很容易让您头疼。

谷歌已经发布了一个关于PHP优化的指南,结论是:

没有getter和setter优化PHP

不,你不能使用魔法方法。对于PHP来说,魔法方法是邪恶的。为什么?

它们很难调试。 会对性能产生负面影响。 它们需要编写更多的代码。

PHP不是Java、c++或c#。PHP是不同的,它遵循不同的规则。

这篇文章不是专门关于__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一般都不好。

There are many ways to create sourcecode in a netbeans-convention. This is nice. It makes thinks such easyer === FALSE. Just use the traditionel, specially if you are not sure which one of the properties should be encapsuled and which one not. I know, it is a boi.... pla... code, but for debugging-works and many other thinks it is the better, clear way. Dont spend to much time with thousend of arts how to make simple getters and setters. You cannot implement too some design patterns like the demeter-rule and so on, if you use magics. In specific situation you can use magic_calls or for small, fast and clear solutions. Sure you could make solutions for design-patters in this way too, but why to make you live more difficult.