php面向对象中的知识总结
2014-10-20 14:35
543 查看
在面向对象中的有一些对象特有的性质:
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 destruct code 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 destruct code 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
"e::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 string1 string2 string3 other 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 string1 string2 string3 other code ... class index destruct
并不是想象中的结果 析构函数在脚本结束的时候才执行,这肯定是还有引用没有销毁, 对 就是静态变量main::$classess ,他会一直呆在内存中,不会因为方法的结束而被摧毁,若增加销毁这个静态变量的代码 main::$classes=null; 将会达到想要的结果
运行如下:
first new
class is exists
class is exists
string1
class index destruct
string2
string3
other 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 ...';
运行结果:
执行请求的方法 string1 class index destruct string2 string3 other code ...
如正如预期的执行!
相关文章推荐
- PHP面向对象知识总结
- PHP面向对象基础知识总结
- PHP面向对象知识总结
- PHP面向对象基础知识总结(2012-07-11)
- php面向对象全攻略 (一) 面向对象基础知识
- php面向对象全攻略 (一) 面向对象基础知识
- 黑马程序员学习log第九篇基础知识:JAVA的面向对象之正则表达式及反射总结
- 黑马程序员_C#面向对象知识总结3
- 记忆总结——java面向对象部分的知识
- 黑马程序员_面向对象知识总结
- 黑马程序员学习log第七篇基础知识:JAVA的面向对象之GUI总结
- PHP 面向对象学习笔记总结
- 黑马程序员学习log第五篇基础知识:JAVA的面向对象之集合总结
- php 面向对象基础总结
- 黑马程序员学习log第六篇基础知识:JAVA的面向对象之IO总结
- php面向对象知识 this,self,parent的区别
- 黑马程序员_C#面向对象学习知识总结1
- PHP 面向对象总结
- php面向对象常用函数总结