本文實例講述了PHP面向對象程序設計之對象克隆clone和魔術方法__clone()用法。分享給大家供大家參考,具體如下:
1.對象克隆 clone
PHP4面向對象功能一個很大的缺點,是將對象視為另一種數據類型,這使得很多常見的OOP方法無法使用,如設計模式。這些方法依賴于將對象作為引用傳遞給其他類方法,而不是作為值傳遞,而按值傳遞卻是PHP的默認做法。幸好,PHP5解決了這個問題,現在所有對象在默認情況下都被視為引用。但是,由于所有對象都被視為引用而不是值,所以現在復制對象更為困難。如果嘗試復制一個引用的對象,這只會指向原對象的地址位置。為了解決復制問題,PHP提供了一種克隆clone
(關鍵字,不是方法)對象的顯式方法。
可以在對象前面加clone
關鍵字來克隆對象,如下:
1
|
destinationObject = clone targetObject; |
克隆對象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?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關鍵字克隆/復制對象,創建一個對象的副本 $person3 = $person1 ; //這不是復制對象,而是為對象多復制出一個訪問該對象的引用 $person1 ->say(); //調用原對象中的說話方式,打印原對象中的全部屬性值 $person2 ->say(); //調用副本對象中的說話方式,打印克隆對象中的全部屬性值 $person3 ->say(); //調用原對象中的說話方式,打印原對象中的全部屬性值 ?> |
2.魔術方法__clone()
在上面的程序中一共創建了兩個對象,其中有一個對象是通過clone
關鍵字克隆出來的副本。兩個對象完全能獨立,但他們中的成員及屬性的值完全一樣。如果需要對克隆后的副本對象在克隆時重新為成員屬性賦初值,則可以在類中聲明一個魔術方法“__clone()”。該方法是在對象克隆時自動調用的,所以就可以通過此方法對克隆后的副本重新初始化。__clone()
方法不需要任何參數。將上例中的代碼改寫一下,在類中添加魔術方法__clone()
,為副本對象中的成員屬性重新初始化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?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 = "李四四" ; //為副本對象中的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()
方法。
首先來看“未做禁止克隆”的效果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?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 true
boolean false
我們“作禁止克隆”處理,即把上面代碼中的
1
|
private function __clone() {} //在__clone()前用private修飾,用來禁止克隆 |
這行代碼去掉注釋。
運行結果為
boolean true
Fatal error: Call to private SingetonBasic::__clone()
也就是,在克隆的時候,自動調用了__clone()
,但是該方法被private
修飾,不能再類的外部直接調用,結果報錯。
希望本文所述對大家PHP程序設計有所幫助。
原文鏈接:https://blog.csdn.net/Yeoman92/article/details/52831259