Mar*_*ark 197 php oop coding-style
我不是一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
或只是公共领域:
class MyClass {
public $firstField;
public $secondField;
}
Run Code Online (Sandbox Code Playgroud)
谢谢
Dav*_*ave 211
你可以使用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;
}
}
?>
Run Code Online (Sandbox Code Playgroud)
Wil*_*iam 111
为什么要使用getter和setter?

mag*_*nes 38
Google已经发布了PHP优化指南,结论如下:
没有getter和setter 优化PHP
不,你不能使用魔法.对于PHP,Magic Method是邪恶的.为什么?
PHP不是Java,C++或C#.PHP是不同的,并扮演不同的角色.
net*_*der 13
封装在任何OO语言中都很重要,流行度与它无关.在动态类型语言(如PHP)中,它特别有用,因为在没有使用setter的情况下,确保属性属于特定类型的方法很少.
在PHP中,这有效:
class Foo {
public $bar; // should be an integer
}
$foo = new Foo;
$foo->bar = "string";
Run Code Online (Sandbox Code Playgroud)
在Java中,它没有:
class Foo {
public int bar;
}
Foo myFoo = new Foo();
myFoo.bar = "string"; // error
Run Code Online (Sandbox Code Playgroud)
使用魔术方法(__get和__set)也有效,但仅在访问可见性低于当前范围的属性时才能访问.如果使用不当,在尝试调试时很容易让您头疼.
如果您想使用__call函数,则可以使用此方法.它适用于
$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;
}
}
Run Code Online (Sandbox Code Playgroud)
除了这里已经很好的和受尊重的答案之外,我想扩展PHP没有setter/getters.
PHP没有getter和setter语法.它提供了子类或魔术方法,允许"挂钩"并覆盖属性查找过程,如 Dave所指出的那样.
Magic允许我们懒惰的程序员在我们积极参与项目并且密切了解它的时候用更少的代码做更多的事情,但通常以牺牲可读性为代价.
性能由于在PHP中强制使用类似getter/setter的代码体系结构而导致的每个不必要的函数都会在调用时涉及自己的内存堆栈帧并浪费CPU周期.
可读性:代码库会产生膨胀的代码行,这会影响代码导航,因为更多的LOC意味着更多的滚动.
偏好:就个人而言,作为我的经验法则,我将静态代码分析的失败作为一个标志,以避免走在神奇的道路上,只要当时没有明显的长期利益.
误区:
一个常见的论点是可读性.例如,$someobject->width比阅读更容易阅读$someobject->width().然而,与行星的circumference或者width可以假设的不同 static,对象的实例(例如$someobject,需要宽度函数)可能需要测量对象的实例宽度.
因此,可读性的增加主要是因为断言命名方案,而不是通过隐藏输出给定属性值的函数.
__get/__set使用:
财产价值的预验证和预先卫生
字符串例如
"
some {mathsobj1->generatelatex} multi
line text {mathsobj1->latexoutput}
with lots of variables for {mathsobj1->generatelatex}
some reason
"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,generatelatex将遵循actionname + methodname的命名方案
特殊,明显的案例
$dnastringobj->homeobox($one_rememberable_parameter)->gattaca->findrelated()
$dnastringobj->homeobox($one_rememberable_parameter)->gttccaatttga->findrelated()
Run Code Online (Sandbox Code Playgroud)注意: PHP选择不实现getter/setter语法.我并不是说getter/setter一般都不好.
小智 6
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
Run Code Online (Sandbox Code Playgroud)
准备!
我使用魔术方法 __call 做了一个实验。不确定我是否应该发布它(因为其他答案和评论中的所有“不要使用魔法方法”警告)但我将把它留在这里......以防万一有人发现它有用。
public function __call($_name, $_arguments){
$action = substr($_name, 0, 4);
$varName = substr($_name, 4);
if (isset($this->{$varName})){
if ($action === "get_") return $this->{$varName};
if ($action === "set_") $this->{$varName} = $_arguments[0];
}
}
Run Code Online (Sandbox Code Playgroud)
只需在您的类中添加上面的方法,现在您可以输入:
class MyClass{
private foo = "bar";
private bom = "bim";
// ...
// public function __call(){ ... }
// ...
}
$C = new MyClass();
// as getter
$C->get_foo(); // return "bar"
$C->get_bom(); // return "bim"
// as setter
$C->set_foo("abc"); // set "abc" as new value of foo
$C->set_bom("zam"); // set "zam" as new value of bom
Run Code Online (Sandbox Code Playgroud)
这样,您可以获取/设置类中的所有内容(如果存在),因此,如果您仅需要少数特定元素,则可以使用“白名单”作为过滤器。
例子:
private $callWhiteList = array(
"foo" => "foo",
"fee" => "fee",
// ...
);
public function __call($_name, $_arguments){
$action = substr($_name, 0, 4);
$varName = $this->callWhiteList[substr($_name, 4)];
if (!is_null($varName) && isset($this->{$varName})){
if ($action === "get_") return $this->{$varName};
if ($action === "set_") $this->{$varName} = $_arguments[0];
}
}
Run Code Online (Sandbox Code Playgroud)
现在您只能获取/设置“foo”和“fee”。
您还可以使用该“白名单”来分配自定义名称以访问您的变量。
例如,
private $callWhiteList = array(
"myfoo" => "foo",
"zim" => "bom",
// ...
);
Run Code Online (Sandbox Code Playgroud)
通过该列表,您现在可以输入:
class MyClass{
private foo = "bar";
private bom = "bim";
// ...
// private $callWhiteList = array( ... )
// public function __call(){ ... }
// ...
}
$C = new MyClass();
// as getter
$C->get_myfoo(); // return "bar"
$C->get_zim(); // return "bim"
// as setter
$C->set_myfoo("abc"); // set "abc" as new value of foo
$C->set_zim("zam"); // set "zam" as new value of bom
Run Code Online (Sandbox Code Playgroud)
。
。
。
就这样。
文档: 在对象上下文中调用不可访问的方法时会触发__call() 。
那么,PHP确实有神奇的方法__get,__set,__isset和__unset,这始终是一个开始.唉正确(得到它?)OO属性不仅仅是魔术方法.PHP实现的主要问题是为所有不可访问的属性调用魔术方法.这意味着在确定name是否实际上是对象的属性时,您必须在魔术方法中重复自己(例如,通过调用property_exists()).除非你的所有类继承自ie,否则你无法用基类真正解决这个一般性问题.ClassWithProperties,因为PHP缺少多重继承.
相比之下,Python新样式类为您提供了property(),它允许您显式定义所有属性.C#有特殊的语法.
http://en.wikipedia.org/wiki/Property_(programming)