首頁 >後端開發 >php教程 >PHP物件導向-物件複製clone和魔術方法__clone()的詳解

PHP物件導向-物件複製clone和魔術方法__clone()的詳解

黄舟
黄舟原創
2017-03-25 10:15:201663瀏覽

1.物件克隆clone

  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();   //调用原对象中的说话方式,打印原对象中的全部属性值?>

2.魔術方法clone()

  在上面的程式中一共創建了兩個對象,其中有一個對像是透過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

3.單例類別的加強:禁止複製

  對於一個類別的對象,如果使用“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
  也就是,在克隆的時候,自動調用了clone(),但是該方法被private修飾,不能再類的外部直接調用,結果報錯。
#######

以上是PHP物件導向-物件複製clone和魔術方法__clone()的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn