您的位置:首页 > 编程语言 > PHP开发

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

2014-12-20 10:59 603 查看
我们都知道,类的私有属性在类外部是不可访问的,包括子类中也是不可访问的。比如如下代码:

<?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 
?> 

但某些情况下我们需要访问类的私有属性,有下面这么几种方法可以实现:
1.利用反射

<?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) 
?> 

2.利用Closure::bind()

此方法是php 5.4.0中新增的。

<?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) 
?> 

另外,我们也可以用引用的方式来访问,这样我们就可以修改类的私有属性:
<?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) 


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

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

<?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(); 
 
//结果输出:我是被动态添加进来的方法 
?>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  php