PHP4中已经有了重载的语法来建立对于外部对象模型的映射,就像Java和COM那样. PHP5带来了强大的面向对象重载,允许程序员建立自定义的行为来访问属性和调用方法,php5加入了如下的内部特征
__construct(); 初始化--构造函数
__destruct(); 卸载--析构函数
__get(); __get方法可以用来捕获一个对象中不存在的变量和方法
__set(); __set方法可以用来捕获和按参数修改一个对象中不存在的变量和方法
__call(); 调用不存在的类的函数的时候得处理方法
__clone(); copy对象用clone $obj;
__sleep(); 串行化的时候用
__wakeup(); 反串行化的时候用
重载可以通过__get, __set, and __call几个特殊方法来进行. 当Zend引擎试图访问一个成员并没有找到时,PHP将会调用这些方法.
在例6.14中,__get和__set代替所有对属性变量数组的访问. 如果必要,你可以实现任何类型你想要的过滤. 例如,脚本可以禁止设置属性值, 在开始时用一定的前缀或包含一定类型的值.
__call方法说明了你如何调用未经定义的方法. 你调用未定义方法时,方法名和方法接收的参数将会传给__call方法, PHP传递__call的值返回给未定义的方法.
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
<?php
class foo {
function __set($name,$val) {
print("
Hello, you tried to put $val in $name");
}
function __get($name) {
print("
Hey you asked for $name");
}
}
$x = new foo();
$x->bar = 3;//注意$bar不存在
print($x->winky_winky);
?>
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
<?php
class foo {
function __call($name,$arguments) {
print("Did you call me? I'm $name!");
}
} $x = new foo();
$x->doStuff(2);
$x->fancy_stuff('a string');
?>
这个特殊的方法可以被用来实现“过载(overloading)”的动作,这样你就可以检查你的参数并且通过调用一个私有的方法来传递参数。
使用 __call 实现“过载”动作
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
<?php
class Magic {
function __call($name,$arguments) {
if($name=='foo') {
print_r($arguments);
if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
}
} private function foo_for_int($x) {
print("
oh an int!");
} private function foo_for_string($x) {
print("
oh a string!");
}
} $x = new Magic();
$x->foo(3);
$x->foo("3");
?>
对一个对象的拷贝通过调用对象的__clone()方法完成
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
<?php
$copy_of_object =clone $obj;
?>
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
<?php
class MyCloneable {
static $id = 0;
function MyCloneable() {
$this->id = self::$id+1; //注意这里如果写self::$id++;将不被充许
}
function __clone() {
$this->address = "New York";
$this->id = self::$id+1;
}
}
$obj = new MyCloneable();
$obj->name = "Hello";
$obj->address = "Tel-Aviv";
print $obj->id . "
";
$obj =clone $obj;
print $obj->id . "
";
print $obj->name . "
";
print $obj->address . "
";
?>
串行化serialize可以把变量包括对象,转化成连续bytes数据. 你可以将串行化后的变量存在一个文件里或在网络上传输. 然后再反串行化还原为原来的数据. 你在反串行化类的对象之前定义的类,PHP可以成功地存储其对象的属性和方法. 有时你可能需要一个对象在反串行化后立即执行. 为了这样的目的,PHP会自动寻找__sleep和__wakeup方法.
当一个对象被串行化,PHP会调用__sleep方法(如果存在的话). 在反串行化一个对象后,PHP 会调用__wakeup方法. 这两个方法都不接受参数. __sleep方法必须返回一个数组,包含需要串行化的属性. PHP会抛弃其它属性的值. 如果没有__sleep方法,PHP将保存所有属性.
例子6.16显示了如何用__sleep和__wakeup方法来串行化一个对象. Id属性是一个不打算保留在对象中的临时属性. __sleep方法保证在串行化的对象中不包含id属性. 当反串行化一个User对象,__wakeup方法建立id属性的新值. 这个例子被设计成自我保持. 在实际开发中,你可能发现包含资源(如图像或数据流)的对象需要这些方法
Object serialization
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
<?php
class User
{
public $name;
public $id;
function __construct()
{
//give user a unique ID 赋予一个不同的ID
$this->id = uniqid();
}
function __sleep()
{
//do not serialize this->id 不串行化id
return(array("name"));
}
function __wakeup()
{
//give user a unique ID
$this->id = uniqid();
}
}
//create object 建立一个对象
$u = new User;
$u->name = "Leon";
//serialize it 串行化 注意不串行化id属性,id的值被抛弃
$s = serialize($u);
//unserialize it 反串行化 id被重新赋值
$u2 = unserialize($s);
//$u and $u2 have different IDs $u和$u2有不同的ID
print_r($u);
print_r($u2);
?>