PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析


Posted in PHP onJune 12, 2019

本文实例讲述了PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法。分享给大家供大家参考,具体如下:

1.对象克隆 clone

PHP4面向对象功能一个很大的缺点,是将对象视为另一种数据类型,这使得很多常见的OOP方法无法使用,如设计模式。这些方法依赖于将对象作为引用传递给其他类方法,而不是作为值传递,而按值传递却是PHP的默认做法。幸好,PHP5解决了这个问题,现在所有对象在默认情况下都被视为引用。但是,由于所有对象都被视为引用而不是值,所以现在复制对象更为困难。如果尝试复制一个引用的对象,这只会指向原对象的地址位置。为了解决复制问题,PHP提供了一种克隆clone(关键字,不是方法)对象的显式方法。

可以在对象前面加clone关键字来克隆对象,如下:

destinationObject = clone targetObject;

克隆对象:

<?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(),为副本对象中的成员属性重新初始化。

<?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()方法。

首先来看“未做禁止克隆”的效果:

<?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

我们“作禁止克隆”处理,即把上面代码中的

private function __clone() {}  //在__clone()前用private修饰,用来禁止克隆

这行代码去掉注释。

运行结果为

boolean true

Fatal error: Call to private SingetonBasic::__clone()

也就是,在克隆的时候,自动调用了__clone(),但是该方法被private修饰,不能再类的外部直接调用,结果报错。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
一个php导出oracle库的php代码
Apr 20 PHP
PHP生成UTF8文件的方法
May 15 PHP
Youku 视频绝对地址获取的方法详解
Jun 26 PHP
php根据分类合并数组的方法实例详解
Nov 06 PHP
PHP正则提取不包含指定网址的图片地址的例子
Apr 21 PHP
PHP遍历目录并返回统计目录大小
Jun 09 PHP
PHP学习笔记(二) 了解PHP的基本语法以及目录结构
Aug 04 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
Aug 21 PHP
微信公众平台开发关注及取消关注事件的方法
Dec 23 PHP
WordPress中用于获取文章作者与分类信息的方法整理
Dec 17 PHP
PHP入门教程之数学运算技巧总结
Sep 11 PHP
Yii2 中实现单点登录的方法
Mar 09 PHP
PHP面向对象程序设计之对象的遍历操作示例
Jun 12 #PHP
PHP面向对象程序设计内置标准类,普通数据类型转为对象类型示例
Jun 12 #PHP
PHP下用Swoole实现Actor并发模型的方法
Jun 12 #PHP
PHP面向对象类型约束用法分析
Jun 12 #PHP
PHP面向对象程序设计__tostring()和__invoke()用法分析
Jun 12 #PHP
php实现微信公众号创建自定义菜单功能的实例代码
Jun 11 #PHP
php转换上传word文件为PDF的方法【基于COM组件】
Jun 10 #PHP
You might like
建立文件交换功能的脚本(一)
2006/10/09 PHP
PHP中创建空文件的代码[file_put_contents vs touch]
2012/01/20 PHP
php使用异或实现的加密解密实例
2013/09/04 PHP
PHP创建word文档的方法(平台无关)
2016/03/29 PHP
CI框架源码解读之利用Hook.php文件完成功能扩展的方法
2016/05/18 PHP
PHP实现验证码校验功能
2017/11/16 PHP
jQuery 锚点跳转滚动条平滑滚动一句话代码
2010/04/30 Javascript
加随机数引入脚本不让浏览器读取缓存
2014/09/04 Javascript
JavaScript字符串对象fromCharCode方法入门实例(用于把Unicode值转换为字符串)
2014/10/17 Javascript
JavaScript将数组转换成CSV格式的方法
2015/03/19 Javascript
Jquery简单实现GridView行高亮的方法
2015/06/15 Javascript
JS如何实现文本框随文本的长度而增长
2015/07/30 Javascript
js 打开新页面在屏幕中间的实现方法
2016/11/02 Javascript
实现一个简单的vue无限加载指令方法
2017/01/10 Javascript
基于JavaScript实现的希尔排序算法分析
2017/04/14 Javascript
Iphone手机、安卓手机浏览器控制默认缩放大小的方法总结(附代码)
2017/08/18 Javascript
详解js几个绕不开的事件兼容写法
2017/08/30 Javascript
json数据传到前台并解析展示成列表的方法
2018/08/06 Javascript
解决JQuery的ajax函数执行失败alert函数弹框一闪而过问题
2019/04/10 jQuery
解决vue单页面修改样式无法覆盖问题
2019/08/05 Javascript
seajs和requirejs模块化简单案例分析
2019/08/26 Javascript
python读取和保存视频文件
2018/04/16 Python
在python带权重的列表中随机取值的方法
2019/01/23 Python
python浪漫表白源码
2019/04/05 Python
使用python模拟高斯分布例子
2019/12/09 Python
Django DRF路由与扩展功能的实现
2020/06/03 Python
css3图片边框border-image的用法
2017/06/30 HTML / CSS
CSS3教程(6):创建网站多列
2009/04/02 HTML / CSS
戴森比利时官方网站:Dyson BE
2020/10/03 全球购物
介绍JAVA 中的Collection FrameWork(及如何写自己的数据结构)
2014/10/31 面试题
一套Delphi的笔试题一
2016/02/14 面试题
经济系大学生求职信
2013/10/01 职场文书
物流专员岗位职责
2014/02/17 职场文书
2014年教师节活动总结
2014/08/29 职场文书
2014学习优秀共产党员先进事迹材料思想汇报
2014/09/14 职场文书
大学自主招生自荐信(2016精选篇)
2016/01/28 职场文书