php中类外部访问类私有属性的方法

Eddy 发布于2013-8-17 17:28:17 分类: 知识积累 已浏览loading 网友评论0条 我要评论

[FONT-SIZE=3]

我们都知道,类的私有属性在类外部是不可访问的,包括子类中也是不可访问的。比如如下代码:
[CODE=php]
class Example1{
private $_prop = 'test';
}

$r = function(Example1 $e){
return $e->_prop;
};

$a = new Example1();
var_dump($r($a));

//运行结果:Fatal error: Cannot access private property Example1::$_prop
?>
[/CODE]
但某些情况下我们需要访问类的私有属性,有下面这么几种方法可以实现:

1.利用反射
[CODE=php]
class Example1{
private $_prop = 'test';
}

$r = function(Example1 $e){
return $e->_prop;
};

$a = new Example1();
$rfp = new ReflectionProperty('Example1','_prop');
$rfp->setAccessible(true);
var_dump($rfp->getValue($a));

//结果输出:string 'test' (length=4)
?>
[/CODE]

2.利用Closure::bind()
此方法是php 5.4.0中新增的。
[CODE=php]
class Example1{
private $_prop = 'test';
}

$r = function(Example1 $e){
return $e->_prop;
};

$a = new Example1();
$r = Closure::bind($r,null,$a);

var_dump($r($a));

//结果输出:string 'test' (length=4)
?>
[/CODE]
另外,我们也可以用引用的方式来访问,这样我们就可以修改类的私有属性:
[CODE=php]
class Example1{
private $_prop = 'test';
}

$a = new Example1();
$r = Closure::bind(function & (Example1 $e) {
return $e->_prop;
}, null, $a);

$cake = & $r($a);
$cake = 'lie';
var_dump($r($a));

//结果输出:string 'lie' (length=3)
[/CODE]


据此,我们可以封装一个函数来读取/设置类的私有属性:
[CODE=php]
$reader = function & ($object, $property) {
$value = & Closure::bind(function & () use ($property) {
return $this->$property;
}, $object, $object)->__invoke();

return $value;
};
?>
[/CODE]

Closure::bind()还有一个很有用之处,我们可以利用这一特性来给一个类动态的添加方法。官方文档中给了这么一个例子:
[CODE=php]
trait MetaTrait
{

private $methods = array();

public function addMethod($methodName, $methodCallable)
{
if (!is_callable($methodCallable)) {
throw new InvalidArgumentException('Second param must be callable');
}
$this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
}

public function __call($methodName, array $args)
{
if (isset($this->methods[$methodName])) {
return call_user_func_array($this->methods[$methodName], $args);
}

throw RunTimeException('There is no method with the given name to call');
}

}

class HackThursday {
use MetaTrait;

private $dayOfWeek = 'Thursday';

}

$test = new HackThursday();
$test->addMethod("addedMethod",function(){
return '我是被动态添加进来的方法';
});

echo $test->addedMethod();

//结果输出:我是被动态添加进来的方法
?>
[/CODE]

[/FONT-SIZE]

已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/skill/884.html     欢迎订阅Eddy Blog

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言