php - getter和setter?

  显示原文与译文双语对照的内容

我不是一个PHP开发人员,所以我想知道,在PHP中使用显式 getter/setter,以纯面向对象的方式使用私有字段( 我喜欢的方式):


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魔术方法__get__set


<?php
class MyClass {
 private $firstField;
 private $secondField;

 public function __get($property) {
 if (property_exists($this, $property)) {
 return $this->$property;
 }
 }

 public function __set($property, $value) {
 if (property_exists($this, $property)) {
 $this->$property = $value;
 }

 return $this;
 }
}
?>

为什么使用getters 和setters?

  1. 的可伸缩性: 重构getter比在项目代码中搜索所有的var赋值更容易。
  2. 调试: 你可以在setter和getter处放置断点。
  3. 干净的: 魔术函数不是较好的编写方法,你的IDE不会让你觉得代码很简单。 更好地使用fast-writting的模板。

direct assignment and getters/setters

封装在任何面向对象语言中都很重要,它与它无关。 在动态类型语言( 比如 PHP ) 中,它是非常有用的,因为很少有方法可以确保属性是特定类型的,而不使用 setter 。

在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 ) 也有效,但只有当访问具有较低可见性的属性时才能访问。 如果没有正确使用的话,它很容易让你感到头疼。


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

就绪 !

如果你使用 __call preffer函数,你可以使用这个方法。 它可以与

  • 获取=> $this->property()
  • 设置=> $this->property($value)
  • 获取=> $this->getProperty()
  • 设置=> $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;
 }
}

除了这里的and和answers的答案外,我想扩展PHP没有 setter 。

磅 PHP没有获取和设置语法 。 它提供了从它派生出子类或魔法方法允许"挂钩"和重写属性查找过程,指出了戴夫 。

魔法允许我们懒惰的程序员与更少的代码做更多的时间我们积极参与项目,知道这亲密,但通常以牺牲可读性。

性能所有不必要的功能,结果迫使一个getter/setter-like code-architecture在php中,涉及到其自己的内存stack-frame调用和浪费cpu周期。

可读性:代码会导致腹胀code-lines,影响code-navigation更多的loc意味着更多的滚动,。

偏好:就我个人而言,我的经验,我把静态代码分析的失败作为一个标志,以避免发生神奇的路上只要明显的长期效益躲避我。

错误:

一个常见的参数是可读性。 例如 $someobject->width$someobject->width() 更易于阅读。 然而与 circumference 行星或 width, 可以认为是 static$someobject 等对象的一个实例,这需要一个宽度函数,可能需要一个测量的实例对象的宽度。
因此可读性增加主要是因为有自信的naming-schemes,而不是隐藏输出给定property-value的函数。

__get/__set使用:

  • 属性值的pre-validation和 pre-sanitation

  • 字符串 e.g.

    
    "
    some {mathsobj1->generatelatex} multi
    line text {mathsobj1->latexoutput}
    with lots of variables for {mathsobj1->generatelatex}
     some reason
    "
    
    

    在这种情况下,generatelatex 将遵循 actionname + 方法的命名方案

  • 特殊的,明显的案例

    
    $dnastringobj->homeobox($one_rememberable_parameter)->gattaca->findrelated()
    $dnastringobj->homeobox($one_rememberable_parameter)->gttccaatttga->findrelated()
    
    

注意: PHP选择不实现获取/设置语法。 我不是说 getter/setter通常是坏的。

...