PHP面向?qū)ο蟪绦蛟O(shè)計(jì)之對(duì)象克隆clone和魔術(shù)方法__clone()用法分析
本文實(shí)例講述了PHP面向?qū)ο蟪绦蛟O(shè)計(jì)之對(duì)象克隆clone和魔術(shù)方法__clone()用法。分享給大家供大家參考,具體如下:
1.對(duì)象克隆 clone
PHP4面向?qū)ο蠊δ芤粋€(gè)很大的缺點(diǎn),是將對(duì)象視為另一種數(shù)據(jù)類型,這使得很多常見(jiàn)的OOP方法無(wú)法使用,如設(shè)計(jì)模式。這些方法依賴于將對(duì)象作為引用傳遞給其他類方法,而不是作為值傳遞,而按值傳遞卻是PHP的默認(rèn)做法。幸好,PHP5解決了這個(gè)問(wèn)題,現(xiàn)在所有對(duì)象在默認(rèn)情況下都被視為引用。但是,由于所有對(duì)象都被視為引用而不是值,所以現(xiàn)在復(fù)制對(duì)象更為困難。如果嘗試復(fù)制一個(gè)引用的對(duì)象,這只會(huì)指向原對(duì)象的地址位置。為了解決復(fù)制問(wèn)題,PHP提供了一種克隆clone
(關(guān)鍵字,不是方法)對(duì)象的顯式方法。
可以在對(duì)象前面加clone
關(guān)鍵字來(lái)克隆對(duì)象,如下:
destinationObject = clone targetObject;
克隆對(duì)象:
<?php class Person{ var $name; var $sex; var $age; function __construct($name, $sex, $age){ $this->name = $name; $this->sex = $sex; $this->age = $age; } function say(){ echo "我的名字:" . $this->name . ",性別:" . $this->sex . ",年齡:" .$this->age . "<br />"; } } $person1 = new Person("張三三", "男", 23); $person2 = clone $person1; //使用clone關(guān)鍵字克隆/復(fù)制對(duì)象,創(chuàng)建一個(gè)對(duì)象的副本 $person3 = $person1; //這不是復(fù)制對(duì)象,而是為對(duì)象多復(fù)制出一個(gè)訪問(wèn)該對(duì)象的引用 $person1->say(); //調(diào)用原對(duì)象中的說(shuō)話方式,打印原對(duì)象中的全部屬性值 $person2->say(); //調(diào)用副本對(duì)象中的說(shuō)話方式,打印克隆對(duì)象中的全部屬性值 $person3->say(); //調(diào)用原對(duì)象中的說(shuō)話方式,打印原對(duì)象中的全部屬性值 ?>
2.魔術(shù)方法__clone()
在上面的程序中一共創(chuàng)建了兩個(gè)對(duì)象,其中有一個(gè)對(duì)象是通過(guò)clone
關(guān)鍵字克隆出來(lái)的副本。兩個(gè)對(duì)象完全能獨(dú)立,但他們中的成員及屬性的值完全一樣。如果需要對(duì)克隆后的副本對(duì)象在克隆時(shí)重新為成員屬性賦初值,則可以在類中聲明一個(gè)魔術(shù)方法“__clone()”。該方法是在對(duì)象克隆時(shí)自動(dòng)調(diào)用的,所以就可以通過(guò)此方法對(duì)克隆后的副本重新初始化。__clone()
方法不需要任何參數(shù)。將上例中的代碼改寫一下,在類中添加魔術(shù)方法__clone()
,為副本對(duì)象中的成員屬性重新初始化。
<?php class Person{ var $name; var $sex; var $age; function __construct($name, $sex, $age){ $this->name = $name; $this->sex = $sex; $this->age = $age; } function say(){ echo "我的名字:" . $this->name . ",性別:" . $this->sex . ",年齡:" .$this->age . "<br />"; } function __clone(){ $this->name = "李四四"; //為副本對(duì)象中的name屬性重新賦值 $this->age = 10; //為副本對(duì)象中的age屬性重新賦值 } } $person1 = new Person("張三三", "男", 23); $person2 = clone $person1; //創(chuàng)建一個(gè)對(duì)象的副本,并自動(dòng)調(diào)用類中的__clone()方法 $person1->say(); //調(diào)用原對(duì)象中的說(shuō)話方式,打印原對(duì)象中的全部屬性值 $person2->say(); //調(diào)用副本對(duì)象中的說(shuō)話方式,打印克隆對(duì)象中的全部屬性值 ?>
運(yùn)行結(jié)果:
我的名字:張三三,性別:男,年齡:23
我的名字:李四四,性別:男,年齡:10
3.單例類的加強(qiáng):禁止克隆
對(duì)于一個(gè)類的對(duì)象,如果使用“clone運(yùn)算符”,就會(huì)復(fù)制出一個(gè)和當(dāng)前對(duì)象完全一樣的新對(duì)象出來(lái),并且,此時(shí)還會(huì)自動(dòng)調(diào)用該類的魔術(shù)方法:__clone()
(只要該類中有該方法)。
則要實(shí)現(xiàn)單例類,就應(yīng)該對(duì)這個(gè)單例類的對(duì)象“禁止克隆”。在PHP中,為防止對(duì)單例類對(duì)象的克隆來(lái)打破單例類的上述實(shí)現(xiàn)形式,通常還為其提供一個(gè)空的私有 (private
修飾的)__clone()
方法。
首先來(lái)看“未做禁止克隆”的效果:
<?php class SingetonBasic { private static $instance; //靜態(tài)變量要私有化,防止類外修改 private function __construct() { //構(gòu)造函數(shù)私有化,類外不能直接新建對(duì)象 } //private function __clone() {} //在__clone()前用private修飾,用來(lái)禁止克隆 public static function getInstance() { //公共的靜態(tài)方法,public——外部的接口,static——不使用對(duì)象而是通過(guò)類名訪問(wèn) if (!(self::$instance instanceof self)) { //私有靜態(tài)變量$instance為空 self::$instance = new self(); //新建為自身的對(duì)象,并賦值給私有變量$instance } return self::$instance; //返回私有變量$instance } } $a = SingetonBasic::getInstance(); $b = SingetonBasic::getInstance(); var_dump($a === $b); //結(jié)果為:boolean true a和b指向的是同一個(gè)對(duì)象 $c = clone $a; var_dump($a === $c); //結(jié)果為:boolean false a和c指向的不是同一個(gè)對(duì)象 ?>
運(yùn)行結(jié)果為
boolean true
boolean false
我們“作禁止克隆”處理,即把上面代碼中的
private function __clone() {} //在__clone()前用private修飾,用來(lái)禁止克隆
這行代碼去掉注釋。
運(yùn)行結(jié)果為
boolean true
Fatal error: Call to private SingetonBasic::__clone()
也就是,在克隆的時(shí)候,自動(dòng)調(diào)用了__clone()
,但是該方法被private
修飾,不能再類的外部直接調(diào)用,結(jié)果報(bào)錯(cuò)。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語(yǔ)法入門教程》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
談PHP生成靜態(tài)頁(yè)面分析 模板+緩存+寫文件
談PHP生成靜態(tài)頁(yè)面 模板+緩存+寫文件,大家可以參考下代碼。2009-08-08PHP向?yàn)g覽器輸出內(nèi)容的4個(gè)函數(shù)總結(jié)
這篇文章主要介紹了PHP向?yàn)g覽器輸出內(nèi)容的4個(gè)函數(shù)總結(jié),本文總結(jié)的就是print()、echo()、printf()、sprintf()這4個(gè)輸出函數(shù),需要的朋友可以參考下2014-11-11基于php實(shí)現(xiàn)長(zhǎng)連接的方法與注意事項(xiàng)的問(wèn)題
本篇文章是對(duì)在php中實(shí)現(xiàn)長(zhǎng)連接的方法與注意事項(xiàng)的問(wèn)題進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05php連接mysql之mysql_connect()與mysqli_connect()的區(qū)別
本擴(kuò)展自 PHP 5.5.0 起已廢棄,并在將來(lái)會(huì)被移除。應(yīng)使用 MySQLi 或 PDO_MySQL 擴(kuò)展來(lái)替換之,這里就為大家分享一下mysql_connect()與mysqli_connect()的區(qū)別,需要的朋友可以參考下2020-07-07php expects parameter 1 to be resource, array given 錯(cuò)誤
從名字可以看出來(lái)這是說(shuō)你傳的參數(shù)有問(wèn)題,也就是說(shuō),你在定義傳遞參數(shù)的時(shí)候 例如 mysql_query($query,$result),這兩個(gè)參數(shù),你只用了$query這個(gè)參數(shù),那么$result這個(gè)參數(shù),沒(méi)有使用,就會(huì)報(bào)這個(gè)錯(cuò)誤2011-03-03用mysql內(nèi)存表來(lái)代替php session的類
mysql內(nèi)存表實(shí)現(xiàn)替換php session類,效果什么大家可以自己測(cè)試下。2009-02-02關(guān)于php 高并發(fā)解決的一點(diǎn)思路
涉及搶購(gòu)、秒殺、抽獎(jiǎng)、搶票等活動(dòng)時(shí),為了避免超賣,那么庫(kù)存數(shù)量是有限的,但是如果同時(shí)下單人數(shù)超過(guò)了庫(kù)存數(shù)量,就會(huì)導(dǎo)致商品超賣問(wèn)題。那么我們?cè)趺磥?lái)解決這個(gè)問(wèn)題呢,我的思路如下2017-04-04