国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 語(yǔ)言 > PHP > 正文

php中淺復(fù)制與深復(fù)制的例子

2024-09-04 11:43:48
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前段時(shí)間頭一次聽(tīng)說(shuō)淺復(fù)制與深復(fù)制了,當(dāng)時(shí)就是看的java例子,下文我來(lái)為各位分享一些小編總結(jié)的php中淺復(fù)制與深復(fù)制的例子供各位學(xué)習(xí).

周末閑來(lái)無(wú)事看到了原型模式,其中談到了淺復(fù)制和深復(fù)制,想到PHP中的對(duì)應(yīng)賦值、克隆以及克隆是淺復(fù)制還是深復(fù)制.

先來(lái)看看賦值,例如有一個(gè)簡(jiǎn)歷類,有身高和體重兩個(gè)屬性:

  1. class Resume  
  2.  
  3.  
  4.     public $height
  5.  
  6.     public $weight
  7.  
  8.    
  9.  
  10.     public $workExperience
  11.  
  12.  
  13. $ResumeA = new Resume(); 
  14.  
  15. $ResumeB = $ResumeA

此時(shí)實(shí)例化了一個(gè)Resume類并賦值給了$ResumeA變量,然后將$ResumeA變量賦值給$ResumeB,PHP手冊(cè)上有說(shuō).

自PHP5起,new運(yùn)算符自動(dòng)返回一個(gè)引用,一個(gè)對(duì)象變量已經(jīng)不再保存整個(gè)對(duì)象的值,只是保存一個(gè)標(biāo)識(shí)符來(lái)訪問(wèn)真正的對(duì)象內(nèi)容,當(dāng)對(duì)象作為參數(shù)傳遞,作為結(jié)果返回,或者賦值給另外一個(gè)變量,另外一個(gè)變量跟原來(lái)的不是引用的關(guān)系,只是他們都保存著同一個(gè)標(biāo)識(shí)符的拷貝,這個(gè)標(biāo)識(shí)符指向同一個(gè)對(duì)象的真正內(nèi)容.

所以若通過(guò)$ResumeB修改height屬性,則$ResumeA也會(huì)跟著變,如果想要復(fù)制一個(gè)全新的對(duì)象,則可以通過(guò)clone來(lái)實(shí)現(xiàn),如.

$ResumeB = clone $ResumeA;

此時(shí)將$ResumeA的值拷貝到新的變量$ResumeB中,改變其中一個(gè)不影響另一個(gè),修改$ResumeB中height屬性,$ResumeA不會(huì)跟著改變。

但如果該類引用了其他對(duì)象,則所有的引用仍然指向到原來(lái)的對(duì)象。clone的這種復(fù)制方式就是淺復(fù)制。被賦值對(duì)象的所有變量都還有與原來(lái)對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用都仍然指向原來(lái)的對(duì)象。

如果上面類中workExperience為WorkExperience類的引用,當(dāng)克隆的時(shí)候,克隆前后的workExperience屬性還是指向到同一個(gè)對(duì)象內(nèi)容.

與淺復(fù)制對(duì)應(yīng)的是深復(fù)制,深復(fù)制把引用對(duì)象的變量指向復(fù)制過(guò)的新對(duì)象,而不是原有的被引用的對(duì)象。

PHP中可以通過(guò)兩種方式來(lái)實(shí)現(xiàn)深復(fù)制,第一種是__clone魔術(shù)方法:

  1. public function __clone() 
  2.  
  3.  
  4.     $this->workExperience = new WorkExperience(); 
  5.  

深復(fù)制涉及深的層次,通過(guò)clone魔術(shù)方法實(shí)現(xiàn)需要知道有幾層然后對(duì)每一層依次實(shí)現(xiàn)。還有一種是可以通過(guò)序列化對(duì)象的方式,先將對(duì)象序列化之后再反序列化,如:

$ResumeB = unserialize(serialize($ResumeA));

clone還算常用的拷貝方式,整理的目的只是為了記錄一下clone是淺復(fù)制,需要注意一下對(duì)象的引用.

我們?cè)倥e一個(gè)更實(shí)用的例子來(lái)說(shuō)明一下PHP clone這種淺拷貝帶來(lái)的后果:

  1. class testClass 
  2.    public $str_data
  3.    public $obj_data
  4. $dateTimeObj = new DateTime("2014-07-05"new DateTimeZone("UTC")); 
  5. $obj1 = new testClass(); 
  6. $obj1->str_data ="aaa"
  7. $obj1->obj_data = $dateTimeObj
  8. $obj2 = clone $obj1
  9. var_dump($obj1);    // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"  //開(kāi)源軟件:Vevb.com 
  10. var_dump($obj2);    // str_data:"aaa"  obj_data:"2014-07-05 00:00:00" 
  11. $obj2->str_data ="bbb"
  12. $obj2->obj_data->add(new DateInterval('P10D'));      //給$obj2->obj_date 的時(shí)間增加了10天 
  13. var_dump($obj1);     // str_data:"aaa"   obj_data:"2014-07-15 00:00:00"  !!!! 
  14. var_dump($obj2);     // str_data:"bbb"   obj_data:"2014-07-15 00:00:00" 
  15. var_dump($dateTimeObj)  // 2014-07-15 00:00:00" 

這一下可以更加清楚的看到問(wèn)題了吧,一般來(lái)講,你用clone來(lái)復(fù)制對(duì)象,希望是把兩個(gè)對(duì)象徹底分開(kāi),不希望他們之間有任何關(guān)聯(lián),但由于clone的shallow copy的特性,有時(shí)候會(huì)出現(xiàn)非你期望的結(jié)果,上面的例子中.

1) $obj1->obj_data =$dateTimeObj 這句話實(shí)際上是個(gè)引用類型的賦值. 還記得前面提到的PHP中對(duì)象直接的賦值是引用操作么?除非你用$obj1->obj_dat = clone $dataTimeObj!

2) $obj2 = clone $obj1 這句話生成了一個(gè)obj1對(duì)象的淺拷貝對(duì)象,并賦給obj2. 由于是淺拷貝,obj2中的obj_data也是對(duì)$dateTimeObj的引用!

3)$dateTimeObj, $obj1->obj_data, $obj2->obj_data 實(shí)際上是同一個(gè)內(nèi)存區(qū)對(duì)象數(shù)據(jù)的引用,因此修改其中任何一個(gè)都會(huì)影響其他兩個(gè)!

如何解決這個(gè)問(wèn)題呢?采用PHP中的 __clone方法 把淺拷貝轉(zhuǎn)換為深拷貝(這個(gè)方法給C++中的copy constructor概念上有些相似,但執(zhí)行流程并不一樣).

  1. class testClass 
  2.  public $str_data
  3.  public $obj_data
  4.  public function __clone() { 
  5.    $this->obj_data = clone $this->obj_data; 
  6. $dateTimeObj = new DateTime("2014-07-05"new DateTimeZone("UTC")); 
  7. $obj1 = new testClass(); 
  8. $obj1->str_data ="aaa"
  9. $obj1->obj_data = $dateTimeObj
  10. $obj2 = clone $obj1
  11. var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00" //開(kāi)源軟件:Vevb.com 
  12. var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00" 
  13. $obj2->str_data ="bbb"
  14. $obj2->obj_data->add(new DateInterval('P10D')); 
  15. var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00" 
  16. var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-15 00:00:00" 
  17. var_dump($dateTimeObj);  //"2014-07-05 00:00:00" 

關(guān)于 __clone() , PHP官方的文檔:Once the cloing is complete, if a __clone() method is defined,then the newly created object’s __clone() method will be called,to allow any necessary properties that need to be changed.

按照這個(gè)定義,事實(shí)上__clone方法可以做很多事情,但我目前能想到的就只有把 淺拷貝變成深拷貝 這個(gè)場(chǎng)景的應(yīng)用了,如果有其他用法,歡迎大家提出來(lái).

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 个旧市| 北宁市| 合阳县| 沁阳市| 兴城市| 马边| 黄龙县| 荣成市| 白朗县| 辛集市| 巴楚县| 连平县| 花莲县| 佛坪县| 涞水县| 凉山| 安顺市| 松原市| 凤山县| 宜良县| 息烽县| 潍坊市| 五台县| 宁南县| 邵阳县| 桂阳县| 通州市| 克拉玛依市| 南投县| 申扎县| 汕头市| 开封县| 泽普县| 龙江县| 五莲县| 长岛县| 卢湾区| 琼中| 师宗县| 榆社县| 广州市|