您的位置:首页 > 编程语言 > PHP开发

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

如正如预期的执行!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息