对象克隆|学习笔记

简介: 快速学习对象克隆

开发者学堂课程【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、可以通过私有化克隆方法来实现禁止外部对象克隆

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

以上就是对象的克隆。

相关文章
|
监控 Linux 调度
浅谈GPU虚拟化技术(四)- GPU分片虚拟化
作者:郑晓,龙欣,弹性计算异构计算项目组 让各位久等了,阿里小二这就开始上新菜:“GPU分片虚拟化”。 对于“分片”的理解,相信大家已经不陌生了。此处的分片从两个维度上来定义:其一,是对GPU在时间片段上的划分,与CPU的进程调度类似,一个物理GPU的计算engine在几个vGPU之间共享,而调...
21839 1
|
Web App开发 JavaScript 前端开发
Android端使用WebView注入一段js代码实现js调用android
Android端使用WebView注入一段js代码实现js调用android
324 0
|
缓存 iOS开发
iOS LaunchScreen.storyboard 启动页设置图片不显示
iOS LaunchScreen.storyboard 启动页设置图片不显示
598 0
|
开发框架 安全
06dwr - web.xml配置(多个 dwr.xml 配置和 J2EE 角色定义)
06dwr - web.xml配置(多个 dwr.xml 配置和 J2EE 角色定义)
91 0
|
JavaScript 前端开发 数据库
Unity3d(webGL)构建数字孪生小案例(包含完整的数据交互体系)附赠完整代码
Unity3d(webGL)构建数字孪生小案例(包含完整的数据交互体系)附赠完整代码,请关注公众号:拼搏的小浣熊,获取简化版的代码!
|
算法 数据可视化 数据挖掘
聚类算法(上):8个常见的无监督聚类方法介绍和比较
本文将全面概述Scikit-Learn库中用于的聚类技术以及各种评估方法。本文作为第一部分将介绍和比较各种聚类算法
974 0
|
JSON JavaScript 前端开发
JSON数据类型
JSON 是 Web 开发中使用最广泛的数据交换格式,它独立于编程语言,能够被大多数编程语言使用。本节我们来详细介绍一下 JSON 中支持的数据类型。
|
存储 SQL JSON
HTTP协议中的“报头”(header)和 “正文“ (body)详解
HTTP协议中的“报头”(header)和 “正文“ (body)详解
HTTP协议中的“报头”(header)和 “正文“ (body)详解
|
消息中间件 Java Kafka
从零搭建基于SpringBoot的秒杀系统(六):使用RabbitMQ让订单指定时间后失效
消息中间件属于分布式系统中一个子系统,关注于数据的发送和接收,利用高效可靠的异步消息传递机制对分布式系统中的其余各个子系统进行集成。java中常用的消息中间件有ActiveMQ、RabbitMQ、Kafka等等。消息中间件的作用主要有系统解耦、异步调用、流量削峰等等。
从零搭建基于SpringBoot的秒杀系统(六):使用RabbitMQ让订单指定时间后失效
|
安全 Java
天天用Synchronized,底层原理是个啥?
Synchronized 的基本使用 Synchronized 的作用主要有三个: 确保线程互斥的访问同步代码 保证共享变量的修改能够及时可见 有效解决重排序问题
天天用Synchronized,底层原理是个啥?