php的魔术方法

从php5以后的版本,类就可以使用魔术方法了。php规定以两个下划线(__)开头的方法都保留为魔术方法,所以建议大家函数名最好不用__开头,除非是为了重载已有的魔术方法。

目前php已有的魔术方法有__construct,__destruct,__call,__get,__set,__isset,__unset,__sleep,__wakeup,__toString,__set_state 和 __clone。

__construct和__destruct是类的构造函数和析构函数,这个大家经常会用到,相信大家都很熟悉,这里就不多说了。

__sleep和__wakeup是序列化类的时候调用的。当序列化对象时,php将试图在序列动作之前调用该对象的成员函数__sleep(),当使用unserialize() 恢复对象时, 将调用__wakeup()。


__toString是对象被转为string时调用的,例如

view plaincopy to clipboardprint?
01.<?php  
02.class Str  
03.{  
04.    private $str;  
05. 
06.    public function __construct($str) {  
07.        $this->str = $str;  
08.    }  
09. 
10.    public function __toString() {  
11.        return $this->str;  
12.    }  
13.}  
14. 
15.$class = new Str('Hello');  
16.echo $class; // 这里对象被转为了string,所以调用了__toString  
17.?> 
<?php
class Str
{
    private $str;

    public function __construct($str) {
        $this->str = $str;
    }

    public function __toString() {
        return $this->str;
    }
}

$class = new Str('Hello');
echo $class; // 这里对象被转为了string,所以调用了__toString
?>
上例将输出 Hello

__set_state是当用var_export()来导出类的时候调用的,这个魔术函数只有一个参数,这个参数是一个数组,用来指定export的时候得到的属性。一般很少用到。

__call, __get和__set 这三个魔术方法是最常用的,当调用类中不存在的方法时就会调用__call,而__get和__set则是访问和设置类不存在的成员变量时调用的。
这三个的函数原型如下:

view plaincopy to clipboardprint?
01.mixed __call(string $name, array $arguments)  
02.void __set(string $name, mixed $value)  
03.mixed __get(string $name) 
mixed __call(string $name, array $arguments)
void __set(string $name, mixed $value)
mixed __get(string $name)
__call的例子:

view plaincopy to clipboardprint?
01.<?php  
02.class Caller  
03.{  
04.    public function __call($method, $args)  
05.    {  
06.        echo "Method $method called:\n";  
07.        print_r($args);  
08.    }  
09.}  
10. 
11.$foo = new Caller();  
12.$foo->test(1, 2);  
13.?> 
<?php
class Caller
{
    public function __call($method, $args)
    {
        echo "Method $method called:\n";
        print_r($args);
    }
}

$foo = new Caller();
$foo->test(1, 2);
?>
上例将输出:
Method test called:
Array
(
    [0] => 1
    [1] => 2
)

__get 和 __set 的例子:

view plaincopy to clipboardprint?
01.<?php  
02.class a  
03.{  
04.    public $c = 0;  
05.    public $arr = array();  
06.      
07.    public function __set($k, $v)  
08.    {  
09.        echo $k . "\n";          
10.        echo $v . "\n";  
11.          
12.        $this->arr[$k] = $v;  
13.    }  
14.      
15.    public function __get($k)  
16.    {  
17.        echo "The value of $k is " . $this->arr[$k];  
18.    }  
19.}  
20.$a = new a;  
21.$a->b = 1; // 成员变量b不存在,所以会调用__set  
22.$a->c = 2; // 成员变量c是存在的,所以不调用__set,无任何输出  
23.$d = $a->b; // 成员变量b不存在,所以会调用__get  
24.?> 
<?php
class a
{
    public $c = 0;
    public $arr = array();
   
    public function __set($k, $v)
    {
        echo $k . "\n";       
        echo $v . "\n";
       
        $this->arr[$k] = $v;
    }
   
    public function __get($k)
    {
        echo "The value of $k is " . $this->arr[$k];
    }
}
$a = new a;
$a->b = 1; // 成员变量b不存在,所以会调用__set
$a->c = 2; // 成员变量c是存在的,所以不调用__set,无任何输出
$d = $a->b; // 成员变量b不存在,所以会调用__get
?>
上例将输出:
b
1
The value of b is 1

__isset和__unset这两个与__get和__set其实原理是差不多的,他们的原型如下:

view plaincopy to clipboardprint?
01.bool __isset(string $name)  
02.void __unset(string $name) 
bool __isset(string $name)
void __unset(string $name)
举个例子:

view plaincopy to clipboardprint?
01.<?php  
02.class a  
03.{      
04.    public $c = 3;  
05.    public $arr = array('a' => 1, 'b' => 2);  
06.      
07.    public function __isset($k)  
08.    {  
09.        return isset($this->arr[$k]);  
10.    }  
11.      
12.    public function __unset($k)  
13.    {  
14.        unset($this->arr[$k]);  
15.    }  
16.}  
17.$a = new a;  
18. 
19.var_dump(isset($a->a)); // 成员变量a不存在,所以调用__isset,返回true  
20.var_dump(isset($a->c)); // 成员变量c是存在的,没有调用__isset,同样返回true  
21.unset($a->b); // 成员变量b不存在,调用__unset  
22.var_dump($a);  
23.?> 
<?php
class a
{   
    public $c = 3;
    public $arr = array('a' => 1, 'b' => 2);
   
    public function __isset($k)
    {
        return isset($this->arr[$k]);
    }
   
    public function __unset($k)
    {
        unset($this->arr[$k]);
    }
}
$a = new a;

var_dump(isset($a->a)); // 成员变量a不存在,所以调用__isset,返回true
var_dump(isset($a->c)); // 成员变量c是存在的,没有调用__isset,同样返回true
unset($a->b); // 成员变量b不存在,调用__unset
var_dump($a);
?>
上例将输出:
bool(true)
bool(true)
object(a)#1 (2) {
["c"]=>
int(3)
["arr"]=>
array(1) {
    ["a"]=>
    int(1)
}
}

类复制(clone)的时候,如果有定义__clone这个魔术方法就会调用它。
举例如下:

view plaincopy to clipboardprint?
01.<?php  
02.class a  
03.{      
04.    public function __clone()  
05.    {  
06.        echo "object cloned\n";  
07.    }  
08.}  
09.$a = new a;  
10. 
11.$b = $a; // $b只是$a的引用,不是克隆,所以不调用__clone,没任何输出。  
12.$c = clone $a; // 调用了__clone,将输出 object cloned  
13.?> 

你可能感兴趣的:(C++,c,PHP,C#)