PHP中 对象自动调用的方法:__set()、__get()、__tostring()
總結:
?(1)__get($property_name):獲取私有屬性$name值時,此對象會自動調用該方法,將屬性name值傳給參數$property_name,通過這個方法的內部
???????????????????????????????????????????? 執行,返回我們傳入 的私有屬性的值。
?(2)__set($property_name, $value):直接給私有屬性賦值時,此對象會自動調用該方法,把屬性比如name傳給$property_name, 把要賦的值
???????????????????????????????????????????????????????? “zhangsan”傳給$value,通過這個方法的執行,達到賦值的目的。
?(3)__tostring()??????????????? : 當直接輸出句柄(可以理解為一個實例)時,會自動執行__tostring()方法。
?
1.__set()與__get().
???????? 一般來說,總是把類的屬性定義為private,這更符合現實的邏輯。但是,對屬性的讀取和賦值操作是非常頻繁的,因此在 PHP5中,預定義了兩個函數
“__get()”和“__set()”來獲取和賦值其屬性,以及檢查屬性的“__isset()”和刪除屬性的方法 “__unset()”。
?????? 我們為每個屬性做了設置和獲取的方法,在PHP5中給我們提供了專門為屬性設置值和獲 取值的方法,“__set()”和“__get()”這兩個方法,這兩個方法不是默認存在的,
而是我們手工添加到類里面去的,像構造方法 (__construct())一樣, 類里面添加了才會存在,可以按下面的方式來添加這兩個方法,當然也可以按個人的風格來添加:
//__get()方法用來獲取私有屬性 public function __get($property_name) {if(isset($this->$property_name)){return($this->$property_name);}else{return(NULL);} }//__set()方法用來設置私有屬性 public function __set($property_name, $value){ $this->$property_name = $value; }__get()方法:這個方法用來獲取私有成員屬性值的,有一個參數,參數傳入 你要獲取的成員屬性的名稱,返回獲取的屬性值,這個方法不用我們手工的去調用,因為我們也可以把這個方法做成私有的方法,是在直接獲取私有屬性的時候對象 自動調用的。因為私有屬性已經被封裝上了,是不能直接獲取值的(比如:“echo $p1->name”這樣直接獲取是錯誤的),但是如果你在類里面加上了這個方法,在使用“echo $p1->name”這樣的語句直接獲取值的時候就會自動調用__get($property_name)方法,將屬性name傳給參 數$property_name,通過這個方法的內部執行,返回我們傳入的私有屬性的值。如果成員屬性不封裝成私有的,對象本身就不會去自動調用這個方 法。
__set()方法:這個方法用來為私有成員屬性設置值的,有兩個參數,第一個參數為你要為設置值的屬性名,第二個參數是要給屬性設置的值, 沒有返回值。這個方法同樣不用我們手工去調用,它也可以做成私有的,是在直接設置私有屬性值的時候自動調用的,同樣屬性私有的已經被封裝上
了, 如果沒有__set()這個方法,是不允許的,比如:$this->name=‘zhangsan’, 這樣會出錯,但是如果你在類里面加上了__set($property_name, $value)這個方法,在直接給私有屬性賦值的時候,就會自動調用它,把屬性比如name傳給$property_name, 把要賦的值“zhangsan”傳給$value,通過這個方法的執行,達到賦值的目的。如果成員屬性不封裝成私有的,對象本身就不會去自動調用這個方 法。為了不傳入非法的值,還可以在這個方法給做一下判斷。代碼如下:
<?php class Person {//下面是人的成員屬性, 都是封裝的私有成員private $name; //人的名子private $sex; //人的性別private $age; //人的年齡//__get()方法用來獲取私有屬性public function __get($property_name) {echo "在直接獲取私有屬性值的時候,自動調用了這個__get()方法<br>";if (isset ( $this->$property_name )) {return ($this->$property_name);} else {return (NULL);}}//__set()方法用來設置私有屬性public function __set($property_name, $value) {echo "在直接設置私有屬性值的時候,自動調用了這個__set()方法為私有屬性賦值<br>";$this->$property_name = $value;} }$per=new person();
$per->name="shirayner"; //此時$per自動調用__set($property_name, $value)方法
echo $per->name; //此時$per自動調用__get($property_name)方法
?>
2.__tostring()
TOstring(在這里故意這么寫,是要說明PHP中方法不區分大小寫,但實際開發中還需要注意規范)。當進行測試時,需要知道是否得出正確的數據。比如打印一個對象時,看看這個對象都有哪些屬
性,其值是什么,如果類定義了toString方法,就能在測試時,echo打印對象體,對象就會自動調用它所屬類定義的toString方法,格式化輸出這個對象所包含的數據。如果沒有這個方法,那么echo一個對
象將報錯,例如“Catchable fatal error:Object of class Account could not be converted tostring”語法錯誤,實際上這是一個類型匹配失敗錯誤。不過仍然可以用print_r()
和var_dump()函數輸出一個對象。當然,toString是可以定制的,所提供的信息和樣式更豐富。 <?php class Account{ public $user=1; private $pwd=2; // 自定義的格式化輸出方法 public function toString(){ return "當前對象的用戶名是{$this->user},密碼是{$this->pwd}"; } } $a=new Account(); echo $a; echo PHP_EOL; print_r($a);
????? 運行這段代碼發現,使用toString方法后,輸出的結果是可定制的,更易于理解。實際上,PHP的toString魔術方法的設計原型來源于 Java。Java中也有這么一個方法,而且在Java中,這個方法被大量使用,對于調試程序比較方便。實際上,toString方法也是一種序列化,我 們知道PHP自帶serialize/unserialize也是進行序列化的,但是這組函數序列化時會產生一些無用信息,如屬性字符串長度,造成存儲空 間的無謂浪費。因此,可以實現自己的序列化和反序列化方法,或者json_encode/json_decode也是一個不錯的選擇。
為什么直接echo一個對象就會報語法錯誤,而如果這個對象實現toString方法后就可以直接輸出呢?原因很簡單,echo本來可以打印一個對 象,而且也實現了這個接口,但是PHP對其做了個限制,只有實現toString后才允許使用。從下面的PHP源代碼里可以得到驗證:
ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY) { zend_op *opline = EX(opline); zend_free_op free_op1; zval z_copy; zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R); // 此處的代碼預留了把對象轉換為字符串的接口 if (OP1_TYPE != IS_CONST && Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL && zend_std_cast_object_tostring(z, &z_copy, IS_STRING TSRMLS_CC) == SUCCESS) { zend_print_variable(&z_copy); zval_dtor(&z_copy); } else { zend_print_variable(z); } ? FREE_OP1(); ZEND_VM_NEXT_OPCODE(); } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的PHP中 对象自动调用的方法:__set()、__get()、__tostring()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 函数体中的全局变量与局部变量
- 下一篇: 黄聪:wordpress如何开启文章格式