我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文代码是基于php的,主角是class类中默认的__clone()方法。所以,本文的一切故事都是通过这个__clone()方法所展开的。

苏南大叔:php教程,class类如何感知到对象克隆事件?如何阻止克隆? - 类感知克隆事件
php教程,class类如何感知到对象克隆事件?如何阻止克隆?(图2-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验总结。本文测试环境:win10nginx@1.15.11php@8.2.10-nts

clone操作与等号操作

不论是哪种编程语言,当“等号”和“高级类型”碰撞的时候,a=b都复制的是内存地址,并不是一个新的对象。修改原来的变量的话,后来的变量也会发生变化,php也是这样的。

测试代码:

class S {
    public function __construct(public string $name){}
}
$s = new S('苏南');
$s2 = $s;
$s3 = clone $s;

var_dump($s2===$s);  // bool(true) 
var_dump($s3===$s);  // bool(false)

$s->name ="sunan";
var_dump($s2->name); // string(5) "sunan"
var_dump($s3->name); // string(6) "苏南"

所以,在php中,也是使用clone关键字操作,才能获得一个完全一样但是并非本体的复制品。

感知clone操作

实际上就是重写类中默认的__clone()方法。测试代码如下:

class S {
    public function __construct(public string $name){}
    public function __clone(){
        echo "正在被克隆";
    }
}
$s = new S('苏南');
echo "=:";
$s2 = $s;
echo "\r\nclone:";
$s3 = clone $s;

输出:

=:
clone:正在被克隆

很显然,=等号操作并不能被称之为克隆,也并不会触发__clone()方法。

禁止克隆操作

禁止某个类被克隆的方案,其实很简单:就是把__clone()方法设置为private私有的。

class S {
    public function __construct(public string $name){}
    private function __clone(){}
}
$s = new S('sunan大叔');
$s3 = clone $s;

苏南大叔:php教程,class类如何感知到对象克隆事件?如何阻止克隆? - 禁止clone
php教程,class类如何感知到对象克隆事件?如何阻止克隆?(图2-2)

这样,就不能在外部使用clone操作了,会得到的错误提示,类似如下:

Fatal error:  Uncaught Error: Call to private S::__clone() from global scope

相关文章

结束语

更多苏南大叔总结的php经验文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php