前面的話
php在面向?qū)ο蟛糠钟泻芏嘞嚓P(guān)的魔術(shù)方法,這些方法為面向?qū)ο髮?shí)現(xiàn)提供了便利,本文將詳細(xì)介紹魔術(shù)方法
構(gòu)造方法
大多數(shù)類都有一種稱為構(gòu)造函數(shù)的特殊方法。當(dāng)創(chuàng)建一個(gè)對象時(shí),它將自動(dòng)調(diào)用構(gòu)造函數(shù),通常用它執(zhí)行一些有用的初始化任務(wù)
構(gòu)造函數(shù)的聲明與其它操作的聲明一樣,只是其名稱必須是兩個(gè)下劃線__construct( )。這是PHP5中的變化;PHP4的版本中,構(gòu)造函數(shù)的名稱必須與類名相同。為了向下兼容,如果一個(gè)類中沒有名為__construct( )的方法,PHP將搜索一個(gè)與類名相同的方法
void __construct ([ mixed $args [, $... ]] )
如果子類中定義了構(gòu)造函數(shù)則不會(huì)隱式調(diào)用其父類的構(gòu)造函數(shù)。要執(zhí)行父類的構(gòu)造函數(shù),需要在子類的構(gòu)造函數(shù)中調(diào)用 parent::__construct()
。如果子類沒有定義構(gòu)造函數(shù)則會(huì)如同一個(gè)普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)
<?phpclass BaseClass { function __construct() { print "In BaseClass constructor "; } }class SubClass extends BaseClass { function __construct() { parent::__construct(); print "In SubClass constructor "; } }
析構(gòu)方法
與構(gòu)造方法相對的就是析構(gòu)方法。析構(gòu)方法是PHP5新添加的內(nèi)容,在PHP4中沒有析構(gòu)方法。析構(gòu)方法是在對象被銷毀之前自動(dòng)調(diào)用的方法,主要執(zhí)行一些特定的操作,例如關(guān)閉文件,釋放結(jié)果集等
與構(gòu)造方法類似,一個(gè)類的析構(gòu)方法名稱必須是兩個(gè)下劃線 __destruct( )。析構(gòu)函數(shù)不能帶有任何參數(shù)
<?phpclass MyDestructableClass { function __construct() { print "In constructor "; $this->name = "MyDestructableClass"; } function __destruct() { print "Destroying " . $this->name . " "; } }//In constructor Destroying MyDestructableClass$obj = new MyDestructableClass();?>
不可訪問屬性
get()
讀取不可訪問屬性(protected、private)時(shí),__get()會(huì)被調(diào)用,并將屬性名以第一個(gè)參數(shù)(string)傳進(jìn)此方法中
public mixed __get ( string $name )
<?phpclass demo{ protected $protected = 1; public $public = 2; private $private = 3; function __get($name){ echo "111{$name}111<br>"; } }$d1 = new demo;$d1->protected;//111protected111$d1->public;$d1->private;//111private111?>
set()
在給不可訪問屬性(protected、private)賦值時(shí),__set() 會(huì)被調(diào)用,并將屬性名以第一個(gè)參數(shù)(string),值作為第二參數(shù)(mixed)傳進(jìn)此方法中
public void __set ( string $name , mixed $value )
<?phpclass demo{ protected $protected = 1; public $public = 2; private $private = 3; function __set($name,$value){ echo "0{$name}0{$value}<br>"; } }
isset()
當(dāng)對不可訪問屬性(protected、private)調(diào)用 isset() 或 empty() 時(shí),__isset() 會(huì)被調(diào)用
public bool __isset ( string $name )
<?phpclass demo{ protected $protected = 1; public $public = 2; private $private = 3; function __isset($name){ echo "0{$name}0<br>"; } }
unset()
當(dāng)對不可訪問屬性(protected、private)調(diào)用unset()時(shí),__unset()會(huì)被調(diào)用
public void __unset ( string $name )
<?phpclass demo{ protected $protected = 1; public $public = 2; private $private = 3; function __unset($name){ echo "0{$name}0<br>"; } }
對象復(fù)制
clone()
在對象克隆時(shí)會(huì)自動(dòng)調(diào)用clone()方法,這方法不需要任何參數(shù),可以通過該方法對克隆后的副本重新初始化
clone()方法會(huì)自動(dòng)包含this和that兩個(gè)對象的引用,this是副本對象的引用,that是原本對象的引用
<?php class Person{ private $name; private $sex; private $age; function __construct($name="",$sex="",$age=1){ $this->name= $name; $this->sex = $sex; $this->age = $age; } function __clone(){ $this->name = $this->name."的副本"; } function say(){ echo "我的名字:" .$this->name.",性別:".$this->sex.",年齡:".$this->age."<br>"; } }
字符串
toString()
__toString()方法用于一個(gè)類被當(dāng)成字符串時(shí)應(yīng)怎樣回應(yīng),它是快速獲取對象的字符串表示的最便捷的方式,是直接輸出對象引用時(shí)自動(dòng)調(diào)用的方法
<?phpclass TestClass{
public $foo; public function __construct($foo)
{
$this->foo = $foo;
} public function __toString() {
return $this->foo;
}
}$class = new TestClass('Hello');echo $class;//Hello?>
對象不存在
call()
在對象中調(diào)用一個(gè)不可訪問方法時(shí),__call()會(huì)被調(diào)用
callStatic()
在靜態(tài)上下文中調(diào)用一個(gè)不可訪問方法時(shí),__callStatic()會(huì)被調(diào)用
<?phpclass MethodTest { public function __call($name, $arguments) { echo "Calling object method '$name' " . implode(', ', $arguments). " "; } public static function __callStatic($name, $arguments) { echo "Calling static method '$name' " . implode(', ', $arguments). " "; } }
自動(dòng)加載類
autoload()
在PHP5中,可以定義一個(gè)__autoload()函數(shù),它會(huì)在試圖使用尚未被定義的類時(shí)自動(dòng)調(diào)用。通過調(diào)用此函數(shù),腳本引擎在PHP出錯(cuò)失敗前有了最后一個(gè)機(jī)會(huì)加載所需的類
<?phpfunction __autoload($class_name) { require_once $class_name . '.php'; }
串行化
sleep()
在調(diào)用serialize()函數(shù)將對象串行化時(shí),檢查類中是否存在一個(gè)魔術(shù)方法 __sleep()。如果存在,該方法會(huì)先被調(diào)用,然后才執(zhí)行序列化操作。此功能可以用于清理對象,并返回一個(gè)包含對象中所有應(yīng)被序列化的變量名稱的數(shù)組。如果該方法未返回任何內(nèi)容,則 NULL 被序列化,并產(chǎn)生一個(gè) E_NOTICE 級別的錯(cuò)誤
__sleep()函數(shù)不需要接受任何參數(shù),但需要返回一個(gè)數(shù)組,在數(shù)組中包含需要串行化的屬性。未被包含在數(shù)組中的屬性將在串行化時(shí)被忽略。如果沒有在類中聲明__sleep()方法,對象中的所有屬性都將被串行化
wakeup()
在調(diào)用unserialize()函數(shù)將對象反串行化對象時(shí),則會(huì)自動(dòng)調(diào)用對象中的__wakeup()方法,用來在二進(jìn)制串重新組成一個(gè)對象時(shí),為新對象中的成員屬性重新初始化
wakeup()經(jīng)常用在反序列化操作中,例如重新建立數(shù)據(jù)庫連接,或執(zhí)行其它初始化操作
<?phpclass Connection { protected $link; private $server, $username, $password, $db; public function __construct($server, $username, $password, $db) { $this->server = $server; $this->username = $username; $this->password = $password; $this->db = $db; $this->connect(); } private function connect() { $this->link = mysql_connect($this->server, $this->username, $this->password); mysql_select_db($this->db, $this->link); } public function __sleep() { return array('server', 'username', 'password', 'db'); } public function __wakeup() { $this->connect(); } }?>
函數(shù)調(diào)用
invoke()
當(dāng)嘗試以調(diào)用函數(shù)的方式調(diào)用一個(gè)對象時(shí),__invoke()方法會(huì)被自動(dòng)調(diào)用
<?phpclass CallableClass { function __invoke($x) { var_dump($x); } }
【補(bǔ)充】
set_state()
當(dāng)調(diào)用var_export()導(dǎo)出類時(shí),set_state()方法會(huì)被調(diào)用,本方法的唯一參數(shù)是一個(gè)數(shù)組,其中包含按 array('property' => value, …) 格式排列的類屬性
[注意]var_export()返回關(guān)于傳遞給該函數(shù)的變量的結(jié)構(gòu)信息,它和var_dump()類似,不同的是其返回的表示是合法的PHP代碼,也就是說,var_export返回的代碼,可以直接當(dāng)作php代碼賦給一個(gè)變量。 而這個(gè)變量就會(huì)取得和被var_export一樣的類型的值
<?phpclass A{
public $var1; public $var2; public static function __set_state($an_array)
{
$obj = new A; $obj->var1 = $an_array['var1']; $obj->var2 = $an_array['var2']; return $obj;
}
}
相關(guān)參考:php中文網(wǎng)