我正在进入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();
看起来我将节省大量时间而不必定义访问器方法。不过我想知道这种方法的优点和缺点是什么?
答案 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:
将您的对象视为其他对象想要使用它或应该做什么。对象不仅仅是数据类型列表。