php面向对象中的知识总结

来源:互联网 发布:淘宝客步骤 编辑:程序博客网 时间:2024/05/20 19:31

在面向对象中的有一些对象特有的性质:

1、对象的引用与拷贝


a、对象的引用 

new返回的是一个实例化对象内存地址的引用

class foo{var $name='init';}$a = new foo;$b = $a;$a->name='abc';echo $b->name;

运行结果:

abc

虽然一般在赋值的时候传递的都是变量的copy,但是在这个例子的结果中

这样 $a=new foo; $a 是一片内存空间的引用 $b = $a 这样 两个变量指向同一片内存空间地址,$a的操作会影响 $b 同样 $b的操作会影响$a


b、对象的拷贝

要是想要copy一份内存 需要使用关键字 clone 并且在使用这个关键字的时候会触发class的魔术方法 __clone

测试代码:

class foo{var $name='init';}$a = new foo;//$b = clone $a;$a->name='abc';echo $b->name;

运行结果:

init

$a对对象数据的操作不能影响到$b 也就是很 两个变量指向的是不同的两个内存地址


2、析构方法的调用时间 __destruct    


析构方法在调用的时候遵循一条规则 当实例化对象的引用全部销毁的时候

a、在函数里面的时候

class dest{private $name='';public function __destruct(){echo 'class name of '.$this->name.' destruct<br>';}public function set($name){$this->name = $name;}}function my(){$index = new dest();echo 'code 1 ................<br>';echo 'code 2 ................<br>';echo 'code 3 ................<br>';}my();echo 'code 4 ................<br>';echo 'code 5 ................<br>';echo 'code 6 ................<br>';

运行结果:

code 1 ................code 2 ................code 3 ................class name of destructcode 4 ................code 5 ................code 6 ................


析构方法在my()函数执行结束的时候调用

原因:在my函数中 $index = new dest() 实例化对象并且将内存地址存储在变量 $index 中,$index 是my函数的局部变量 当函数执行完毕会回收(销毁)局部变量 $index ,

$index 是dest实例化对象的唯一引用,销毁的时候触发析构方法

b、当实例化对象有多个引用的时候

class foo{public function __destruct(){echo "destruct function <br>";}}$a = new foo;//$a $b 指向同样的一个内存片段 也就是说类foo实例化对象有两个引用$b = $a;echo "code 1 ....... <br>";$b=null; // 销毁一个并不会触发执行析构方法 因为还有引用存在echo "code 2 ....... <br>";$a=null; // 所有对这个对象的引用全部销毁,执行析构方法echo "code 3 ....... <br>";echo "code 4 ....... <br>";

运行结果:

code 1 ................code 2 ................code 3 ................class name of destructcode 4 ................code 5 ................code 6 ................

这说明 当一个实例化对象存在多个引用的时候,要将这些引用全部销毁的时候才执行析构方法

c、当脚本执行完毕的时候 php解释器会销毁所有的变量 这时候可能会销毁一些还存在的对象引用 从而触发执行析构方法


3、函数/方法的引用返回


正常情况的函数中的return返回的都是变量的一份copy如要返回变量的引用,需要这样的函数

function &func_name(){return $var;}

如下例子:

class quote{public static $name=0;public static function &test(){return self::$name;}}//返回的是静态变量 quote::$name 的引用而非copy$a = & quote::test();$a++;$a++;echo quote::$name; //2

运行结果:

2

&quote::test() 返回的是静态变量 quote::$name 的引用 并赋值给$a 这样可以通过$a对静态变量进行操作


4、call_user_func_array 函数的使用


调用静态类方法 

call_user_func_array(array('index','test'), $args_arr);

调用非静态 类方法

$index = new index;call_user_func_array(array($index,'test'), $args_arr);

这个函数就是将 要调用的function 、class-method的代码片段 写在函数存在的位置上


通过上面的知识基础开始分析如下:

1、单例 对象

通过静态变量存储实例化过的class下次在次使用的时候返回存储的class

class main{public static $classes=array();public static function run(){$a = self::load_class('index');$b = self::load_class('index');$c = self::load_class('index');echo "string1<br>";echo "string2<br>";echo "string3<br>";}public static function load_class($class){//保证对象只实例化一次if(!array_key_exists($class, self::$classes)){echo 'first new <br>';self::$classes[$class]=new $class;}else{echo 'class is exists <br>';}return self::$classes[$class];}}class index{public $name='';public function set($name){$this->name=$name;}public function test(){}public function __destruct(){echo '<br>class index destruct<br>';}}main::run();echo '<br>other code ...';
运行结果:
first new class is exists class is exists string1string2string3other code ...class index destruct

第一次new的时候会实例化到内存,后面的则直接返回引用 这时候的变量 $a $b $c main::$classes 四个变量全都是事例化对象 index 的引用

class main{public static $classes=array();public static function run(){$a = self::load_class('index');$b = self::load_class('index');$c = self::load_class('index');echo "string1<br>";// 销毁实例对象的引用 触发析构方法$a=null$b=null;$c=null;echo "string2<br>";echo "string3<br>";}public static function load_class($class){//保证对象只实例化一次if(!array_key_exists($class, self::$classes)){echo 'first new <br>';self::$classes[$class]=new $class;}else{echo 'class is exists <br>';}return self::$classes[$class];}}class index{public $name='';public function set($name){$this->name=$name;}public function test(){}public function __destruct(){echo '<br>class index destruct<br>';}}main::run();echo '<br>other code ...';

运行结果:

first new class is exists class is exists string1string2string3other code ...class index destruct

并不是想象中的结果 析构函数在脚本结束的时候才执行,这肯定是还有引用没有销毁, 对 就是静态变量main::$classess ,他会一直呆在内存中,不会因为方法的结束而被摧毁,若增加销毁这个静态变量的代码  main::$classes=null;   将会达到想要的结果

运行如下:

first new class is exists class is exists string1class index destructstring2string3other code ...

但是这样并不是很方便,虽然实现了只加载一份class到内存,但是多次调用会产生过多的指针,导致难以操作。通过函数/方法的引用返回会有所优化:

class main{public static $classes=array();public static function run(){$index = &self::load_class('index');call_user_func_array(array($index,'test'), array());echo "string1<br>";//销毁唯一的对象引用 触发析构方法$index = null;echo "string2<br>";echo "string3<br>";}public static function &load_class($class){//保证对象只实例化一次if(!array_key_exists($class, self::$classes)){self::$classes[$class]=new $class;}//这里返回的是 这个静态变量的引用 同时这个静态变量是实例化对象的唯一指针return self::$classes[$class];}}class index{public $name='';public function test(){echo '执行请求的方法<br>';}public function __destruct(){echo 'class index destruct<br>';}}main::run();echo 'other code ...';

运行结果:
执行请求的方法string1class index destructstring2string3other code ...

如正如预期的执行!微笑









0 0
原创粉丝点击