每个公共财产都必须有访问方法吗?

时间:2010-08-11 16:36:18

标签: php oop object

我正在进入OOP,我遇到了以下两难困境。我有一个班级:

class Recipe {

    var $title;
    var $time;
    var $ingredients = array();
    var $instructions;
    var $category;

    function __construct($title, $time, $ingredients, $instructions, $category) {

        $this->title = $title;
        ...
    }

    function getTitle() {
        return $this->title;
    }

}

所有属性都是公共的(默认情况下)。我是否必须为所有这些属性(例如getTitle)定义访问器方法,或者我可以直接引用属性,如下所示:

...
$recipe = new Recipe($title, $time, $ingredients, $instructions, $category);
echo $recipe->title; // versus $recipe->getTitle();

看起来我将节省大量时间而不必定义访问器方法。不过我想知道这种方法的优点和缺点是什么?

5 个答案:

答案 0 :(得分:4)

OOP的黄金法则始终将您的属性设为私有!很少有公共财产被允许的情况,但即使这样,也可能有另一种解决方案。

原因是:如果您公开您的财产,任何人都可以将其更改为他们想要的任何内容。大多数属性不能只是任何值。你的$ title属性应该是一个整数吗?我非常怀疑它。那么如果你或其他人不小心将它设置为整数呢?你不会发现它。它将设置值,您的程序将继续运行,直到它失败,因为某个地方有一个字符串。此外,您的房产可能会在设置之前以某种方式进行验证。您可以将所有这些验证包含在酒店的设置者中。

即使您不需要验证属性,您仍然最好将它们置于getter和setter之后,以防最终确实需要验证它。

使您的属性保持私密状态,确保在不应该使用对象时不会混淆,避免由此产生的任何错误。 :)

有时你会想“好吧,只有我会编辑我的代码,所以什么都不会发生”。但是你应该现在练习。养成做这件事的习惯。你以后会避免任何麻烦。

答案 1 :(得分:4)

我会说不应该使用不必要的setter / getter加载,尤其是在PHP中,或者你的应用程序可能会变得非常慢。 这是一个简单的例子:

<?php
class Recipe {

    public $title;

    function __construct($title){
        $this->title = $title;
    }

    function getTitle(){
        return $this->title;
    }

}

$a = new Recipe('potatoes');
$t1 = microtime(true);
for($i=0;$i<1000000;$i++){
    $x = $a->title;
}
$t2 = microtime(true) - $t1;
echo $t2.'s<br/>';

$a = new Recipe('potatoes');
$t1 = microtime(true);
for($i=0;$i<1000000;$i++){
    $x = $a->getTitle();
}
$t2 = microtime(true) - $t1;
echo $t2.'s<br/>';

?> 

回声:

0.25662112236023s

1.0309250354767s

用吸气剂慢4倍!

答案 2 :(得分:4)

Getters / Setters在大多数脚本语言中都不受欢迎。它们最初是专门用Java和Java Bean引入的。在静态编译的代码中,强封装是有意义的。在脚本语言中,无论如何所有访问都通过解释器,而不是直接通过内存地址;因此有魔术方法。在PHP中,您可以通过__get路由所有内容,使包装器变得多余。

getter / setter的用例是精心设计过滤和验证方案。除非你提出一个具体的属性,否则准备空心的setter是没有意义的(getter很少转换这些值)。

答案 3 :(得分:3)

公共属性不需要getter / setter方法,但它会使您更容易出错。使用访问器还可以强制对数据进行验证,而直接设置公共属性可以允许设置任何数据。

如果您利用PHP的魔术功能,您可以编写动态getter / setter方法来访问私有/受保护的属性。

<?php


/**
 * Implements auto get/set
 * class Entity extends GetterSetter {}
 * $name = $entity->getName(); // return $this->name;
 * $name = $entity->getFullName(); // return $this->full_name;
 * $entity->setFullName("Ian"); // $this->full_name = "Ian";
 */

class GetterSetter {
    public function __call($name, $args) {
        if (substr($name, 0, 3) == "get") {
            $key = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', (substr($name, 3, strlen($name)-3))));
            if (property_exists($this, $key)) {
                //print "/* GET " . $this . "->" . $key . " = " . $this->$key . "\n */";
                return $this->$key;
            }
        } elseif (substr($name, 0, 3) == "set") {
            $key = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', (substr($name, 3, strlen($name)-3))));
            if (property_exists($this, $key)) {
                //print "/* SET " . $this . "->" . $key . " = " . $args[0] . "\n */";
                return ($this->$key = $args[0]);
            } else {
                print "Key not found: " . $this . "->" . $key;
            }
        }
    }

}
?>

答案 4 :(得分:2)

使用getter / setter:

  • 您可以更改实施。例如,稍后您可以更改getTime以计算$指令的数量,而不是使用成员$ time。
  • Setter可以抛出异常,验证输入或新状态,更改其他数据,记录,......

将您的对象视为其他对象想要使用它或应该做什么。对象不仅仅是数据类型列表。