在類當中,設計通用的set和get方法,可以簡化對屬性的讀寫,這種方法不同於針對於獨立的屬性的普通的get和set方法,后者針對每個屬性,都必須提供一對方法,前者針對所有屬性,因此,可以看作是批量定義set和get方法的策略。
另外一種常見的魔術方法是construct,在這里作為對照進行介紹。
第一,關於訪問權限修飾符。construct設計為public,那么可以在new創建對象時,系統會調用構造方法對對象進行初始化,否則將無法實例化此類(常用於純靜態類,或者單例模式當中),而set和get,設計為private並不影響功能本身,即系統調用這些方法是不受訪問權限所左右的。而設計為public,則可以直接調用這些方法本身。
第二,關於返回值。get方法的返回值,作為屬性結果,而construct和set方法的返回值是沒有任何意義的,並不會被采用。如下:
echo $obj->pro = "value";
打印的值將是value,而不論set方法的返回值是什么。
第三,關於使用的情境。需要取得$obj->pro值的情況下,會首先尋找公共的pro屬性,如果沒有找到,會查看是否有get方法,並將其返回值作為結果,如果沒有get方法,將會尋找私有屬性,找到后會報錯,如果私有屬性也找不到,會臨時創建一個公共屬性。
<?php class User{ private $id; private $name; } $user = new User(); $user->ac = 6;//不報錯,臨時產生一個公共屬性 echo $user->ac; ?>
在$obj->pro = "value"的情況下,會首先尋找公共pro屬性,如果沒有找到,會啟用set方法,如get類似。
上述語法,在類本身也有用,如果類的某個方法有$obj->pro的表達式,那么,它會首先尋找屬性,然后采用get方法,當然,私有屬性和公共屬性都會被首先尋找,然后才會考慮get方法,set方法類似。
但是isset魔術方法,是優先於get方法的,也就是說,如果客戶端代碼如下:
isset($obj->pro),會首先檢查是否有pro公共變量,然后檢查isset方法,如果有,將會讀取isset方法,然后將返回值確定為檢查結果,如果沒有,才會考慮用get方法的過程。
第四,關於繼承。這些魔術方法均會被子類繼承,繼承時,父類可以訪問子類中的非私有變量和方法,但是無法訪問私有變量和方法。這個問題會導致一個值得注意的細節,比如在父類當中,我們把set方法定義為賦值給一個叫_pro的變量,那么,如果子類直接繼承這個set方法,它將能夠有效賦值給父類當中定義的私有變量,但是對於子類當中的私有變量,它並沒有多態的權限,因此,無法賦值。
class User{ private $id; private $name = "jiangbo"; public function __get($property_name) { if(isset($this->$property_name)) { if($property_name == "cd"){ return $this->_cdtime; } return($this->$property_name); } else { return("no find"); } } //__set()方法用來設置私有屬性 public function __set($property_name, $value) { $this->$property_name = $value; } } $user = new User(); echo $user->ac;//"no find" echo "<br>"; echo $user->name;