我不是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;
}
如果你喜欢使用__call函数,你可以使用这个方法。它适用于
GET => $this->属性()
SET => $this->属性($value)
getProperty() => $this->
SET => $this->setProperty($value)
kalsdas
public function __call($name, $arguments) {
//Getting and setting with $this->property($optional);
if (property_exists(get_class($this), $name)) {
//Always set the value if a parameter is passed
if (count($arguments) == 1) {
/* set */
$this->$name = $arguments[0];
} else if (count($arguments) > 1) {
throw new \Exception("Setter for $name only accepts one parameter.");
}
//Always return the value (Even on the set)
return $this->$name;
}
//If it doesn't chech if its a normal old type setter ot getter
//Getting and setting with $this->getProperty($optional);
//Getting and setting with $this->setProperty($optional);
$prefix = substr($name, 0, 3);
$property = strtolower($name[3]) . substr($name, 4);
switch ($prefix) {
case 'get':
return $this->$property;
break;
case 'set':
//Always set the value if a parameter is passed
if (count($arguments) != 1) {
throw new \Exception("Setter for $name requires exactly one parameter.");
}
$this->$property = $arguments[0];
//Always return the value (Even on the set)
return $this->$name;
default:
throw new \Exception("Property $name doesn't exist.");
break;
}
}
在阅读了其他建议后,我倾向于这样说:
作为GENERIC规则,你不会总是为所有属性定义setter,特别是“内部”属性(信号量、内部标志……)。只读属性显然没有setter,所以有些属性只有getter;这就是__get()缩小代码的地方:
define a __get() (magical global getters) for all those properties which are alike,
group them in arrays so:
they'll share common characteristics: monetary values will/may come up properly formatted, dates in an specific layout (ISO, US, Intl.), etc.
the code itself can verify that only existing & allowed properties are being read using this magical method.
whenever you need to create a new similar property, just declare it and add its name to the proper array and it's done. That's way FASTER than defining a new getter, perhaps with some lines of code REPEATED again and again all over the class code.
是的!我们也可以写一个私有方法来做到这一点,但话又说回来,我们将声明许多方法(++内存),最终调用另一个总是相同的方法。为什么不写一个单一的方法来管理它们呢?(是的!双关语!)):
Magic setter也可以只响应特定的属性,因此可以单独在一个方法中筛选所有日期类型属性的无效值。如果日期类型属性列在数组中,则可以轻松定义它们的setter。当然,这只是一个例子。有太多的情况。
About readability... Well... That's another debate: I don't like to be bound to the uses of an IDE (in fact, I don't use them, they tend to tell me (and force me) how to write... and I have my likes about coding "beauty"). I tend to be consistent about naming, so using ctags and a couple of other aids is sufficient to me... Anyway: once all this magic setters and getters are done, I write the other setters that are too specific or "special" to be generalized in a __set() method. And that covers all I need about getting and setting properties. Of course: there's not always a common ground, or there are such a few properties that is not worth the trouble of coding a magical method, and then there's still the old good traditional setter/getter pair.
编程语言就是人类的人工语言。因此,它们都有自己的语调或重音、语法和风格,所以我不会假装用与Java或c#相同的“重音”来编写Ruby或Python代码,也不会编写类似Perl或SQL的JavaScript或PHP……用他们该用的方式去使用他们。
class MyClass {
private $firstField;
private $secondField;
private $thirdField;
public function __get( $name ) {
if( method_exists( $this , $method = ( 'get' . ucfirst( $name ) ) ) )
return $this->$method();
else
throw new Exception( 'Can\'t get property ' . $name );
}
public function __set( $name , $value ) {
if( method_exists( $this , $method = ( 'set' . ucfirst( $name ) ) ) )
return $this->$method( $value );
else
throw new Exception( 'Can\'t set property ' . $name );
}
public function __isset( $name )
{
return method_exists( $this , 'get' . ucfirst( $name ) )
|| method_exists( $this , 'set' . ucfirst( $name ) );
}
public function getFirstField() {
return $this->firstField;
}
protected function setFirstField($x) {
$this->firstField = $x;
}
private function getSecondField() {
return $this->secondField;
}
}
$obj = new MyClass();
echo $obj->firstField; // works
$obj->firstField = 'value'; // works
echo $obj->getFirstField(); // works
$obj->setFirstField( 'value' ); // not works, method is protected
echo $obj->secondField; // works
echo $obj->getSecondField(); // not works, method is private
$obj->secondField = 'value'; // not works, setter not exists
echo $obj->thirdField; // not works, property not exists
isset( $obj->firstField ); // returns true
isset( $obj->secondField ); // returns true
isset( $obj->thirdField ); // returns false
准备好了!