PHP中的淺複製與深複製的實例詳解
#前言:
最近重溫了一下Design Pattern方面的知識,在看到Prototype Pattern這一設計模式時,注意到其中涉及到一個淺複製與深複製的問題。這裡來總結一下,提醒自己以後一定要多加註意。
自PHP5起,new運算子自動傳回一個引用,一個 物件變數 已經不再儲存整個物件的值,只是保存一個識別碼來存取真正的物件內容。當物件作為參數傳遞,作為結果返回,或者賦值給另一個變量,另外一個變量跟原來的不是引用的關係,只是他們都保存著同一個標識符的拷貝,這個標識符指向同一個對象的真正內容。
這裡舉個栗子:
class Example1 { public $name; public function construct($name) { $this->name = $name; } } $ex1 = new Example('test1');// $ex1->name现在是:test1 $ex2 = $ex1;// $ex2->name现在是:test1 $ex2->name = 'test2';// 这样修改一下之后,$ex1->name与$ex2->name都变为了:test2
透過上面這個例子,應該可以理解物件間引用的概念了,那麼我們繼續往下走,在php中提供了clone 這個關鍵字來進行物件複製,還是用上面的類別來示範:
$ex1 = new Example('test1');// $ex1->name现在是:test1 $ex2 = clone $ex1;//$ex2->name现在是:test1 $ex2->name = 'test2';//现在$ex1->name还是test1,而$ex2->name是test2
這裡看到,透過clone之後,$ex1與$ex2是兩個不同的對象,他們擁有各自的變數環境。但這裡要注意,在這兩個物件內部,擁有的是值類型的數據,如果是內部擁有的是引用類型,那麼透過clone得到的新物件中的引用則仍然指向原引用。這裡就引申出淺複製與深複製的概念:
淺複製: 使用clone來複製對象,這種複製叫做“淺複製“,被賦值對象的所有變數都還有與原來物件相同的值,而所有的其他物件的參考都仍然指向原來的物件。
深複製:被複製的物件的所有的變數都含有與原來的物件相同的值,除去那些引用其他物件的變數。
預設使用 clone 是進行一個淺複製,那麼如何才能進行深複製呢?
方式一:利用clone方法
public function clone() { $this->obj = new Obj(); }
這種方式非常直觀,但是卻有一個很麻煩的操作方式,就是當類別中包含多當你被引用時,你就需要在clone方法中逐一重新設定。而且還要處理一些循環引用的問題。是很複雜的。
方式二:利用串列化(冷藏與解凍)
$tmp = serialize($ex1); $ex2 = unserialize($tmp);
這時候得到的$ex2就是一個全新的對象,這個過程在java中也叫作」冷藏「與」解凍「過程。
序列化是一個遞歸的過程,我們不需要理會被物件內部引用了多少個物件以及引用了多少層對象,我們都可以徹底的複製。方式二真的很黃很暴力,但我很喜歡。
以上是php中關於淺複製和深複製的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!