php面向对象——对象的传递方式
2020-06-29 04:51
926 查看
理论基础
- 传值赋值 (赋值运算),将原变量的值拷贝到新变量中,所以改变其中一个并不影响另一个,适合于在密集循环中拷贝一些值例如大数组
- 引用赋值,使用
$var= &$othervar
语法,引用赋值意味着两个变量指向了同一个数据,没有拷贝任何东西 - 在php5中,一个对象变量并不是保存整个对象的值,而是保存一个对象标识符来访问真正的对象内容,因此,当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容
对象的传值赋值
对象的传值赋值结论
当我们把一个对象赋给另一个对象时即
$p2 = $p1,是值拷贝(传值赋值),但是拷贝的不是数据本身,而是对象标识符
对象传值赋值示例1
class Person{ public $name; public $age; } $p1 = new Person(); $p1->name = '金角大王'; $p1->age = 300; $p2 = $p1; $p2->name = '银角大王'; echo $p1->name,'<br>'; echo $p2->name,'<br>'; var_dump($p1,$p2);
示例1 内存图
- 内存中有代码区,栈区,数据区
- 代码区负责编译,所有要执行的代码必须先被加载到代码区
- 栈区负责运行代码,代码区的代码被逐条扔进栈区进行运行
- 数据区负责存放数据
示例1 内存流程详解
栈区运行
$p1=new Person代码
- 导致数据区生成一个对象内存,存放
name=null age=null
两个数据 - 同时,会产生一个对象标识符
#1
,$p1
指向#1
,#1
指向对象内存
栈区运行
$p1->name=’金角‘代码
p1
先找到对象的标识符#1
,然后通过标识符#1
找到对象内存- 然后修改对应的属性值
栈区运行
$p2 = $p1代码
$p2 = $p1
是传值赋值,p1
指向的是对象标识符#1
,因此将对象标识符#1
拷贝了一份,此时有两个标识符#1
p2
指向新拷贝的标识符#1
- 对象标识符一样,自然指向同一个对象内存
栈区运行
$p2->name=’银角代码
p2
先找到对象的标识符#1
,然后通过标识符#1
找到对象内存- 然后修改对应的属性值
对象传值赋值示例2
class Person{ public $name; } $p1 = new Person(); $p1->name = 'aa'; $p2 = $p1; $p2 = 'abc'; echo $p1->name,'<br>'; // '银角大王' echo $p2->name,'<br>'; // 自然报错,p2指向的是字符串 echo $p2; // 'abc'
示例2 内存图
对象的引用赋值
对象的引用赋值结论
当我们把一个对象赋给另一个对象时
$p2 = &$p1,也是值拷贝(传值赋值),但是拷贝的不是数据本身,而是对象标识符
对象引用赋值示例1
class Person{ public $name; } $p1 = new Person(); $p1->name = 'aa'; $p2 = &$p1; // 引用赋值 p1 p2指向同一个标识符#1 $p2 = 'abc'; //echo $p1->name,'<br>'; // 报错,p1指向的是字符串,因#1标识符已经改为了字符串 //echo $p2->name,'<br>'; // 报错,p2指向的是字符串 var_dump($p1,$p2); // string 'abc' string 'abc'
示例1 内存图
对象引用赋值示例2
class Person{ public $name; } $p1 = new Person(); $p1->name = 'aa'; $p2 = &$p1; $p2->name = 'abc'; echo $p1->name,'<br>'; // abc echo $p2->name,'<br>'; // abc var_dump($p1,$p2);
示例2 内存图
对象引用赋值示例3
class Person{ public $name; } $p1 = new Person(); $p1->name = 'aa'; $p2 = &$p1; $p2->name = 'abc'; unset($p2); echo $p1->name,'<br>'; // abc echo $p2->name,'<br>'; // 未定义变量:p2 var_dump($p1,$p2); // object(Person)[1] null
示例3 内存图
注意:unset() 销毁的是变量,并不是内存
对象的克隆
class Person{ private $name; public function __construct($name){ $this->name = $name; } } $p1 = new Person('aa'); $p2 = clone $p1; if ($p1 == $p2){ echo '$p1==$p2<br>'; } var_dump($p1,$p2); // object(Person)[1] object(Person)[2]
对象的比较
注意是对象的比较,非对象不适用
- 当使用比较运算符(==)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等
- 如果使用全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)
对象传值赋值
class Person{ private $name; public function __construct($name){ $this->name = $name; } } $p1 = new Person('aa'); $p2 = $p1; if ($p1 === $p2){ echo '$p1===$p2<br>'; } var_dump($p1,$p2); // object(Person)[1] object(Person)[1]
对象引用赋值
class Person{ private $name; public function __construct($name){ $this->name = $name; } } $p1 = new Person('aa'); $p2 = &$p1; if ($p1 === $p2){ echo '$p1===$p2<br>'; } var_dump($p1,$p2); // object(Person)[1] object(Person)[1]
实例化新对象
class Person{ private $name; public function __construct($name){ $this->name = $name; } } $p1 = new Person('aa'); $p2 = new Person('aa'); if ($p1 == $p2){ echo '$p1==$p2<br>'; } var_dump($p1,$p2); // object(Person)[1] object(Person)[2]
克隆对象
class Person{ private $name; public function __construct($name){ $this->name = $name; } } $p1 = new Person('aa'); $p2 = clone $p1; if ($p1 == $p2){ echo '$p1==$p2<br>'; } var_dump($p1,$p2); // object(Person)[1] object(Person)[2]
克隆对象和实例化新对象比较
需求: 将对象整体复制一份,两种方法都能实现
- 实例化新对象比较low,麻烦,需要传值,且p1如果修改属性值的话就不一样了
- clone不仅完全一样,且clone可以配合__clone魔术方法,在clone完成时,自动调用__clone魔术方法,修改属性值
class Person{ private $name; public function __construct($name){ $this->name = $name; } // 在clone完成时,__clone魔术方法自动被调用,可以用于修改克隆来的属性值 public function __clone(){ $this->name = 'abc'; } } $p1 = new Person('aa'); $p2 = clone $p1; var_dump($p1,$p2); // object(Person)[1] object(Person)[2]
如何阻止对象克隆
修改__clone魔术方法为private,可以阻止对象被克隆
class Person{ private $name; public function __construct($name){ $this->name = $name; } // 修改__clone魔术方法为private,可以阻止对象被克隆 private function __clone(){} } $p1 = new Person('aa'); $p2 = clone $p1; // 报错
非对象的传递方式
非对象是没有对象标识符的,标识符为对象特有的
非对象传值赋值
$a = 'hello'; $b = $a; if ($a===$b){ echo '$a===$b'; // $a===$b }
非对象引用赋值
$a = 'hello'; $b = &$a;
延伸
class Person{ public $name; } $p1 = new Person(); $a = [1,2,5,['zz',$p1]]; $b = $a; if ($a===$b){ echo '$a===$b'; // $a===$b } $b[3][1]->name = '唐僧'; var_dump($a,$b); // 两个值都改了
相关文章推荐
- PHP对象在内存中的存在形式,函数传递内存方式
- PHP面向对象——实例化对象时向构造函数传递参数
- php面向对象(一) 初窥(php面向对象基础介绍)
- vue-axios-post方式传递对象至后台
- php面向对象视频笔记之第二章(面向对象初步)
- Android --- 使用Intent传递对象的方式
- php数组和对象的值传递和引用传递
- JS 面向对象 创建对象 对象在内存分配 对象调用 其他函数 或 其他对象成员 构造函数 通过call或apply执行函数 获取构造器 new Function()方式创建一个函数出来
- PHP页面之间传递参数的四种方式
- Java String对象以“引用”方式被传递
- PHP中数组,字符串和对象的在方法中的引用方式
- Intent传递对象的两种方式
- PHP 5.0对象模型深度探索之访问方式
- PHP回调函数类型传递方式总结
- 命令行向Php传递参数的两种方式
- JS面向对象二:js对象的几种创建方式
- 【深入PHP 面向对象】读书笔记(一) - 发展介绍与对象基础
- 【面向对象】php新手之学习类与对象-构造函数与析构函数
- java的方法重载,面向对象的概念,编写类以及创建对象,成员变量与局部变量的区别,构造方法以及构造方法的重载,空指针异常,封装,this关键字,参数传递,static关键字,继承的概念及相关代码
- 前端学PHP之面向对象系列第一篇——类和对象