前面我们已经知道,使用传址引用的方式调用对象,实质调用的是同一个对象,有时需要建设立一个对象的副本,改变原来的对象时不希望影响到副本,在PHP中可以根据现在的对象来克隆出一个完全一样的对象,克隆出来的副本和原本两个对象完全独立而互不干扰。

 

我们举个简单的例子来看一下克隆的用法​


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19




​<?php​

​header(​​​​"content-type:text/html;charset=utf-8"​​​​);​

​class​​ ​​Character{                                                       ​​​​//定义一个角色类​

​public​​ ​​$name​​​​;​

​protected​​ ​​$location​​​​;​

​function​​ ​​__construct(​​​​$name​​ ​​, ​​​​$location​​​​)              ​​​​//创建构造函数​

​{​

​$this​​​​->name = ​​​​$name​​​​;​

​$this​​​​->location = ​​​​$location​​​​;​

​}​

​function​​ ​​play(){                                                      ​​​​//创建方法​

​echo​​ ​​'我要玩'​​ ​​.  ​​​​$this​​​​->name.​​​​$this​​​​->location;​

​}​

​}​

​$character1​​ ​​= ​​​​new​​ ​​Character(​​​​'亚索'​​​​,​​​​'中单'​​​​);                ​​​​//实例化一个类​

​$character2​​ ​​= ​​​​clone​​ ​​$character1​​​​;                               ​​​​//将实例化的类再克隆出来一个​

​$character1​​​​->play();                                                    ​​​​//调用方法执行​

​echo​​ ​​'<br/>'​​​​;​

​$character2​​​​->play();​


上述实例的结果都是‘我要玩亚索中单’。

上面我们说到克隆的副本和原本独立而互不干扰,这句话又是什么意思呢?

还是上面的实例,只是稍微发生点变动。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20




​<?php​

​header(​​​​"content-type:text/html;charset=utf-8"​​​​);​

​class​​ ​​Character{                                                       ​​​​//定义一个角色类​

​public​​ ​​$name​​​​;​

​public​​ ​​$location​​​​;​

​function​​ ​​__construct(​​​​$name​​ ​​, ​​​​$location​​​​)              ​​​​//创建构造函数​

​{​

​$this​​​​->name = ​​​​$name​​​​;​

​$this​​​​->location = ​​​​$location​​​​;​

​}​

​function​​ ​​play(){                                                      ​​​​//创建方法​

​echo​​ ​​'我要玩'​​ ​​.  ​​​​$this​​​​->name.​​​​$this​​​​->location;​

​}​

​}​

​$character1​​ ​​= ​​​​new​​ ​​Character(​​​​'亚索'​​​​,​​​​'中单'​​​​);                ​​​​//实例化一个类​

​$character2​​ ​​= ​​​​clone​​ ​​$character1​​​​;​

​$character2​​​​->location = ​​​​'上单'​​​​;​

​$character1​​​​->play();                                                    ​​​​//调用方法执行​

​echo​​ ​​'<br/>'​​​​;​

​$character2​​​​->play();​


上述实例的结果就是‘我要玩亚索中单’和'我要玩亚索上单'。

由例子可以看出克隆出来的副本和原本两个对象完全独立而互不干扰。

__clone的用法

很多时候我们不单单要去克隆一个对象,还想让对象可以拥有自己的属性和方法。那么我们就要在类中创建一个__clone方法。这个方法类似于构造函数和析构函数,因为不会直接调用它。

还是以上面的实例为例:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22




​<?php​

​header(​​​​"content-type:text/html;charset=utf-8"​​​​);​

​class​​ ​​Character{                                                       ​​​​//定义一个角色类​

​public​​ ​​$name​​​​;​

​public​​ ​​$location​​​​;​

​function​​ ​​__construct(​​​​$name​​ ​​, ​​​​$location​​​​)              ​​​​//创建构造函数​

​{​

​$this​​​​->name = ​​​​$name​​​​;​

​$this​​​​->location = ​​​​$location​​​​;​

​}​

​function​​ ​​__clone(){​

​$this​​ ​​-> location = ​​​​'上单'​​​​;​

​}​

​function​​ ​​play(){                                                      ​​​​//创建方法​

​echo​​ ​​'我要玩'​​ ​​.  ​​​​$this​​​​->name.​​​​$this​​​​->location;​

​}​

​}​

​$character1​​ ​​= ​​​​new​​ ​​Character(​​​​'亚索'​​​​,​​​​'中单'​​​​);                ​​​​//实例化一个类​

​$character2​​ ​​= ​​​​clone​​ ​​$character1​​​​;​

​$character1​​​​->play();                                                    ​​​​//调用方法执行​

​echo​​ ​​'<br/>'​​​​;​

​$character2​​​​->play();​


__clone方法的一个很好的特性就是在使用默认行为创建一个副本之后能够被调用,这样,在这个阶段,可以只改变希望改变的内容。

在__clone方法中添加的最常见功能就是确保作为引用进行处理的类属性能够正确的复制。如果要克隆一个包含对象引用的类,可能需要获得该对象的第二个副本,而不是该对象的第二个引用,因此这就是为什么要在__clone方法中添加该代码的原因。