1. 程式人生 > >php中類外部訪問類私有屬性的方法

php中類外部訪問類私有屬性的方法

我們都知道,類的私有屬性在類外部是不可訪問的,包括子類中也是不可訪問的。比如如下程式碼:

<?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) 
?>
 
<?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($methodNamearray $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外部訪問私有屬性方法

我們都知道,類的私有屬性在類外部是不可訪問的,包括子類中也是不可訪問的。比如如下程式碼: <?php   class Example1{      private $_prop = 'test';  }    $r = function(Example1 $e){ 

php在物件之外訪問私有屬性private及保護屬性protected的特例

程式碼如下,在這種情況下php允許訪問私有及保護屬性: class yunke { protected $a = 55; private $b = 66; public fu

php的物件的私有屬性遍歷-----預定義的介面iterator

物件的屬性名與值類似於關聯陣列的鍵名與鍵值,物件從這個角度來看與關聯陣列很相似,所以php中的物件可以使用foreach進行遍歷public的屬性。程式碼如下: 當對一個物件使用foreach時預設是對公有屬性的遍歷,但公有屬性的遍歷沒有實際的意義,在很多的框架中是允許對某個物件中的私

php自動加載_autoload()和spl_autoload_register()實例詳解

http obj 自動加載 完整 echo register auto 文件名 代碼 一、_autoload 自動加載類:當我們實例化一個未定義的類時,就會觸此函數。到了php7.1以後版本不支持此函數好像拋棄了   新建一個類文件名字自己隨便去:news類在auto.ph

PHPAES加密解密

我們在工作中會遇到各種加密,下面就是PHP中AES加密解密的類 <?php  class Aes {     /**      * var string&nbs

JAVA中子繼承了父私有屬性方法了嗎?

一、繼承知識點簡單梳理 1、繼承會獲得父類的屬性和方法,子類還能有自己的屬性方法。       開閉原則:對修改關閉,對擴充套件開啟。 2、JAVA支援單繼承(一個子類只能有一個直接父類)、支援多重繼承(A extends B,B extends C)。       JAV

phpforeach遍歷物件的總結

foreach 遍歷陣列很常見,同樣foreach也可以遍歷物件 做如下測試: class my { public $a = 'a'; protected $b = 'b'; private $c = 'c'; private $data = array('fant

外部呼叫私有方法

public class PrivateTest { private String saySing(String name) { return "hello : "+name; } } import java.lang.Class; import java

JavaScript閉包實現的私有屬性的getter()和setter()方法

參數 strong prop nbsp body 利用 edi 獲取 展示 註意: 以下的輸出都在瀏覽器的控制臺中 <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g

Python進階-----的內置item屬性方法

return style __init__ 進階 mean val 才會 方式 self 類的內置item相關方法只有在通過字典key操作才會觸發而通過點的方式來操作,則觸發attr相關方法 class Foo: def __init__(self,name,ag

PHP防止非法訪問

在使用者訪問頁面時,不一定按照正常的規則來訪問,而是進行一些非法訪問,為此我們需要禁止非法訪問。 我學會了兩種禁止非法訪問的方法↓↓↓ 1.empty if(empty($_POST)){ die('非法訪問'); } 判斷如果從HTML檔案接收資訊的$

php二維數組排序問題方法詳解

ges cti cmp each ace esc 對數 x11 用法 PHP中二維數組排序,可以使用PHP內置函數uasort() 示例一: 使用用戶自定義的比較函數對數組中的值進行排序並保持索引關聯 回調函數如下:註意回調函數的返回值是負數或者是false的時候,表

PHP調用SVN命令更新網站方法(解決文件名包含中文更新失敗的問題)

設置 php tro 參數 名稱 www 文件 命令 更新失敗 想說寫一個通過網頁就可以執行 SVN 升級的程序,結果並不是我想得那樣簡單,有一些眉角需要註意的說。 先以 Apache 的用戶帳號執行 SVN checkout,這樣 Apache 才有 SVN 的鏈結權力,

phpstatic和self調用靜態方法區別

php由於看到框架裏面經常使用static::method() 於是稍微了解下static和self的區別廢話少說,直接上代碼class Father { public function __construct() { $this->init(); self::test(); }

PHPXML和陣列互相轉換的方法

轉換程式碼如下 //陣列轉XML function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key=>$val) {

PHP 提示undefined index如何解決(多種方法)

PHP 中提示undefined index如何解決(多種方法) 這篇文章主要介紹了PHP 中提示undefined index如何解決(多種方法)的相關資料,需要的朋友可以參考下 一、相關資訊 平時用$_post['']或$_get['']獲取表單中引數時會出現Notice: Undefined i

OpenCV6種訪問Mat元素的方法

Mat中不管是以at訪問還是ptr訪問,都是行優先 ,先Y軸後X軸(即先行後列) 1、使用at訪問 /* *OpenCV2中Mat的at操作訪問矩陣元素 * */ #include <highgui.h> using namespace std ; using namespa

關於PHPPDO抽象層,採用rowCount();方法出現返回結果為0的解決方案

在學PHP的過程中,遇到一些問題,但不是全部都能夠順利得到解決,就在PDO抽象層,採用rowCount();方法出現數據能夠正常查詢出來的情況下返回結果為0,在網上搜了一天,沒有一個具體的說明和解決方案,很多朋友在問,但卻沒有人回答,因此在這裡稍微說說具體的情況及最終的解決

在Unity3D載入外部圖片的兩種方法

  各位朋友大家好,我是秦元培,歡迎大家關注我的部落格。最近在做專案的過程中遇到這樣的一個需求:玩家可以在遊戲過程中進行實時存檔,在存檔過程中會儲存當前遊戲進度,同時會擷取當前遊戲畫面並載入到遊戲存檔介面中。當下一次進入遊戲的時候,將讀取本地存檔圖片並載入到

vue-cil專案使用外部js的3種方法

vue-cil專案中 1. 匯入屬性的方法 新建 ./api/api.js import Vue from 'vue'; Vue.prototype.test=function () { alert(111) } 在main.js 中匯入