PHP4物件導向功能一個很大的缺點,是將物件視為另一種資料型別,這使得許多常見的OOP方法無法使用,例如設計模式。這些方法依賴將物件作為引用傳遞給其他類別方法,而不是作為值傳遞,而按值傳遞卻是PHP的預設做法。幸好,PHP5解決了這個問題,現在所有物件在預設情況下都被視為引用。但是,由於所有物件都被視為引用而不是值,所以現在複製物件更為困難。如果嘗試複製一個引用的對象,這只會指向原始對象的地址位置。為了解決複製問題,PHP提供了一種克隆clone(關鍵字,不是方法)物件的明確方法。
可以在物件前面加上clone關鍵字來複製對象,如下:
destinationObject = clone targetObject;
複製物件:
<?phpclass 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关键字克隆/复制对象,创建一个对象的副本 $person3 = $person1; //这不是复制对象,而是为对象多复制出一个访问该对象的引用 $person1->say(); //调用原对象中的说话方式,打印原对象中的全部属性值 $person2->say(); //调用副本对象中的说话方式,打印克隆对象中的全部属性值 $person3->say(); //调用原对象中的说话方式,打印原对象中的全部属性值?>
在上面的程式中一共創建了兩個對象,其中有一個對像是透過clone關鍵字克隆出來的副本。兩個物件完全能獨立,但他們中的成員及屬性的值完全一樣。如果需要對克隆後的副本物件在複製時重新為成員屬性賦初值,則可以在類別中宣告一個魔術方法「clone()」。該方法是在物件克隆時自動呼叫的,所以就可以透過此方法對克隆後的副本重新初始化。 clone()方法不需要任何參數。將上例中的程式碼改寫一下,在類別中加入魔術方法clone(),為副本物件中的成員屬性重新初始化。
<?phpclass 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 = "李四四"; //为副本对象中的name属性重新赋值 $this->age = 10; //为副本对象中的age属性重新赋值 } }$person1 = new Person("张三三", "男", 23); $person2 = clone $person1; //创建一个对象的副本,并自动调用类中的clone()方法 $person1->say(); //调用原对象中的说话方式,打印原对象中的全部属性值 $person2->say(); //调用副本对象中的说话方式,打印克隆对象中的全部属性值?>
運行結果:
我的名字:张三三,性别:男,年龄:23 我的名字:李四四,性别:男,年龄:10
對於一個類別的對象,如果使用“clone運算子”,就會複製出一個和當前物件完全一樣的新物件出來,並且,此時還會自動呼叫該類別的魔術方法:clone()(只要該類別中有該方法)。
則要實作單例類,就應該對這個單例類的物件「禁止複製」。在PHP中,為防止對單例類別物件的複製來打破單例類別的上述實作形式,通常也為其提供一個空的私有 (private修飾的)clone ()方法。
首先來看「未做禁止克隆」的效果:
<?php class SingetonBasic { private static $instance; //静态变量要私有化,防止类外修改 private function construct() { //构造函数私有化,类外不能直接新建对象} // private function clone() {} //在clone()前用private修饰,用来禁止克隆 public static function getInstance() { //公共的静态方法, public——外部的接口,static——不使用对象而是通过类名访问 if (!(self::$instance instanceof self)) { //私有静态变量$instance为空 self::$instance = new self(); //新建为自身的对象,并赋值给私有变量$instance } return self::$instance; //返回私有变量$instance} }$a = SingetonBasic::getInstance();$b = SingetonBasic::getInstance(); var_dump($a === $b); //结果为:boolean true a和b指向的是同一个对象$c = clone $a; var_dump($a === $c); //结果为:boolean false a和c指向的不是同一个对象?>
運行結果為
boolean trueboolean false
我們「作禁止克隆」處理,即運行結果為
private function clone() {} //在clone()前用private修饰,用来禁止克隆
我們「作禁止克隆」處理,即把上面程式碼中的boolean trueFatal error: Call to private SingetonBasic::clone()
這行程式碼去掉
。
運行結果為
rrreee以上是PHP物件導向-物件複製clone和魔術方法__clone()的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!