对象克隆|学习笔记

简介: 快速学习对象克隆

开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第一阶段对象克隆】学习笔记,与课程紧密联系,让用户快速学习知识。  

课程地址:https://developer.aliyun.com/learning/course/711/detail/12674


对象克隆

 

内容介绍:

一、学习对象克隆

二、小结

 

一、学习对象克隆

接下来学习对象克隆。在人类自然圈里面,有一种技术叫克隆,比如克隆羊多利,它就是从本体产生另一个相似的本体,是一个独立的品种。

这节课将学习对象的克隆,也就是产生对象。本节的目标是:了解对象克隆的概念,掌握克隆魔术方法的意义。

1.概念

(1)克隆对象:clone 关键字,这是需要用到的关键字。即通过已有的对象复制一个新的同样的对象,但是两者之间是独立的,并非同一个对象。

①克隆对象与原来对象内容一致(这只是一种表象,当前一样,未来未必一样)

②克隆出来的对象是新对象

③对象克隆出来后会自动调用魔术方法 _clone (前提是这个方法已经定义,否则不会调用)

2.步骤

(1)定义类时需要考虑对象是否允许被克隆,以及考虑如果允许克隆后是否需要针对克隆的新对象做的操作,还有如果不允许克隆,就有以下:

①不允许克隆:可以私有化 clone (魔术方法(不允许外部克隆,所有的私有化克隆方法都不允许类的外部调用。使用者一般都是外部)

②允许克隆处理:在 clone() 方法中设定好克隆对象的处理

(2)实例化对象并保存到变量

(3)需要从已有对象克隆产生新对象(不是赋值)

(4)使用 clone 产生对象

3.示例

(1)克隆对象是通过 clone 关键字实现,即:clone 加上对象代表的变量。

比如说:

Class Saler{

#属性

public $count;

private $money;

}

这里定义了一个类。

#实例化

$s1 = new Saler()

$s1->count

这里实例化产生了一个对象,对里面的属性做了一个复制,复制是为了证明克隆出来的对象和现有状态是一致的,而不是原始对象。因此复制与否也不重要。

#克隆

$s2 = clone $s1

克隆,把 $s1 克隆变成 $s2。

(2)具体案例

如图:

image.png

输入 15.php ,然后写入以下代码:

<?php

#对象克隆

比如说:

Class Saler{

#属性

public $count;

private $money;

}

#实例化

$s1 = new Saler()

$s1->count

#克隆

$s2 = clone $s1

输入代码后,打印这两个对象,查看它们是否是同一个对象。

如图:

image.png

输入:var_dump($s1,$s2)

然后运行,如图:

image.png

可以看到,第一个 s1 的编号为1,第二个s2 等待编号为2,此时已经可以说明它们是两个对象了,也就是说存在两个对象,而且两个对象的内容是一样的。这里的 count 值为1,说明 s2 克隆的对象是 s1 到目前状态为止的所有状态,即前面做的操作都会被克隆。这就是对象克隆产生新对象。

(3)证明两个对象不同

证明两个对象不同,可以修改一其中个对象的值,然后看对另外一个对象的值是否有影响。

输入:

#修改

$s2->count = 2;

var_dump($s1,$s2)

如图:

image.png

对 $2进行修改,把它的 count 值从1改为2。

运行,如图:

image.png

可以看到,第一个依旧是1,而第二个已经从1变成2了,也就是说,修改一个对象并不会影响另外一个对象,这足以说明它们两个是完全不同的对象。

以上可以说明克隆出来的是新对象。

(4)对象在实例化的时候会自动调用存在的构造方法__construct(),同样的,在类的内部,PHP 允许定义一个__clone 也就是克隆的方法,在对象被克隆后,新克隆出来的对象会自动调用这个方法。

把证明的代码删除,然后输入:

<?php2

#对象克隆

class Saler{

#属性

public $count;

private $money;

#克隆魔术方法

public function __clone

echo __METHOD__;

#实例化

$s1 new Saler();

$s1->count = 1;

#克隆

$s2 cLone $s1;

加上一个克隆魔术方法,这个方法是系统自己定义的,先去证明它们被调用了,把克隆先注释,此时这个方法是不会被调用的,但是一旦把注释删除,

如图:

image.png

可以看到,此时克隆方法被调用了。以上就是克隆魔术方法。

(5)如何证明被克隆出来的对象是调用了原来的方法,还是原来的对象 s1 在调用?

①方法一

如图:

image.png

在克隆魔术方法中加入:var_dump($this);

刷新页面,如图:

image.png

可以看到,是对象 s2 调用了方法。

②方法二

如图:

image.png

修改对象,输入:$this->money = 10;然后输入:var_dump($s1,$s2);在外部打印这个对象而不是打印 this

刷新页面,如图:

image.png

可以看到,第一个是1,编号为1,count 为1,money 等于 NULL ,说明没有被修改。而第二个的 money 是10,说明当前内部修改的 this 是 s2 对象。

这就是克隆对象调用克隆方法的一个特点。

 

(6)如果不允许对象被克隆,可以将 __clone() 方法私有化,与构造方法一样不需要外部实例化,也不需要外部克隆。

如图:

image.png

把克隆私有化,即把 public 改为 private。同时忽略所有 var_dump($s1,$s2);的打印,给其注释。

刷新页面,如图:

image.png

可以看到,克隆出来的对象会马上调用方法,而这里不允许克隆,因此报错。

所以还需要把克隆注释,如图:

image.png

这些代码是不允许执行的。

重新刷新页面,如图:

image.png

由于不允许克隆,因此不会有对象克隆出来。这样从内部防止了外部克隆对象,这也是克隆的一个特点。

 

二、小结

1、对象可以通过克隆来得到新的对象

以前只有实例化才能产生新对象,现在克隆也可以产生新对象,

2、克隆出来的对象会自动调用类中对应的 __clone() 方法

如果没有方法,就不会调用,但是如果有,就一定会自动调用。

3、因为克隆对象是新对象,它不会改变原来的对象。

所以希望在当前对象达到某种临界点时候,需要复制但是后面可能还需要使用它,保留它的状态的时候使用克隆。如果需要一个和当前对象一致状态的对象,但是又不想改变当前对象的状态,那么就可以通过克隆来实现

4、可以通过私有化克隆方法来实现禁止外部对象克隆

因为每次对象进行克隆都是对内存的消耗,所以如果不需要或者不希望克隆的时候,可以通过私有化克隆方法来实现禁止外部对象克隆。如果这个类是给其他用户使用的,一般就需要这样操作,如果是自己使用,就无需这样操作。

以上就是对象的克隆。

相关文章
|
7月前
原型模式——克隆
原型模式——克隆
46 0
|
存储
【克隆方法+深浅拷贝】
【克隆方法+深浅拷贝】
70 0
|
Java 编译器 Apache
每日面试题之介绍一下克隆!
每日面试题之介绍一下克隆!
|
JavaScript
原生js实现对象的克隆
原生js实现对象的克隆
原生js实现对象的克隆
jira项目笔记25-删除对象中的一些属性
jira项目笔记25-删除对象中的一些属性
94 0
jira项目笔记25-删除对象中的一些属性
原型模式:克隆生成对象
原型模式的本质是克隆生成对象
970 0
原型模式:克隆生成对象
|
Java 开发者
对象克隆|学习笔记
快速学习对象克隆
101 0
|
Shell 开发工具 git
如何只克隆部分代码?
如何只克隆部分代码? 一、需求 根据整体规划需求,多个模块的源码共存在一个仓库中。在一些场景执行中,需要考虑执行效率,仅关注部分路径的代码。即仅需获取部分路径的文件。 二、解决方案 利用Sparse Checkout模式。
1238 0