在面向对象语言中,有一个很重要的概念——overload,即重载。所谓重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同。但是,在php中,这个概念跟大多面向对象语言中的“重载”一点关系都没有,根本就是风马牛不相及的。
php中的重载,是指动态地"创建"类属性和方法。当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。再说的直白点,就是访问一个类或者对象的不可访问的属性或者方法的时候的一种处理机制。(不可访问,比如不存在或者因访问关键字的限制而不能访问)
1、属性重载
四个魔术方法:
1)__get($属性名)
访问对象中不可访问的属性的时候,会自动调用该方法
2)__set($属性名,$属性值)
给对象中不可访问的属性赋值的时候,会自动调用该方法。方法中的两个参数,依次代表所访问的属性和对应的值。
3)__isset($属性名)
当对一个对象不可访问的属性进行isset()或者empty()判断的时候,会自动调用该方法。
4)__unset($属性名)
当对一个对象不可访问的属性进行unset()销毁的时候,会自动调用该方法。
使用的代码如下:
<?php header("Content-type:text/html;charset = utf-8"); class Test{ public $p1 = 1; function __get($property) {//访问不可访问属性的时候,会自动调用该方法 echo "不可访问的属性:{$property}"; } function __set($property,$value) {//对不可访问的属性赋值,会自动调用该方法 echo "对不可访问的属性{$property} 赋值 {$value}<br/>"; } function __isset($property){//对不可访问的属性进行isset判断,会自动调用该方法 echo "对不可访问的属性{$property}进行isset判断<br/>"; } function __unset($property){//对不可访问的属性进行unset操作,会自动调用该方法 echo "对不可访问的属性{$property}进行unset操作<br/>"; } } $t = new Test(); echo $t->p1."<br/>"; echo $t->p2."<br/>"; //给不可访问的属性进行赋值 $t->p3 = 2; //对不可访问的属性进行isset判断 isset($t->p4); //对不可访问的属性进行unset操作 unset($t->p5); /* 运行结果: 1 不可访问的属性:p2 对不可访问的属性p3 赋值 2 对不可访问的属性p4进行isset判断 对不可访问的属性p5进行unset操作 */ ?>
配合是用__get()和__set()方法,可以使类变得更加灵活和自由,可以很方便给类添加属性。如下:
<?php header("Content-type:text/html;charset = utf-8"); class Test{ //定义数组,用于存储不可访问的属性 protected $plist = array(); function __get($property) {//访问不可访问属性的时候,会自动调用该方法 //属性不可访问,从plist中读取 if (isset($this->plist[$property])) { return $this->plist[$property]; } else { return "属性{$property}不可访问"; } } function __set($property,$value) {//对不可访问的属性赋值,会自动调用该方法 //属性不可访问,将之存放到plist中 $this->plist[$property] = $value; } function __isset($property){//对不可访问的属性进行isset判断,会自动调用该方法 $v = isset($this->plist[$property]); return $v; } function __unset($property){//对不可访问的属性进行unset操作,会自动调用该方法 unset($this->plist[$property]); } } $t = new Test(); $t->p1 = 1;//对不可访问的属性赋值 echo "不可访问的属性p1的值为:".$t->p1."<br/>";//使用p1属性(经过上一行代码,p1已经添加到了plist中) echo "不可访问的属性p2的值为:".$t->p2."<br/>";//没对p2赋值过 //分别对p1和p2进行isset操作 $r1 = isset($t->p1);//结果为true,但是如果不处理__isset魔术方法,将返回false $r2 = isset($t->p2);//结果为false,本来也不存在... var_dump($r1);echo "<br/>"; var_dump($r2);echo "<br/>"; //分别对p1和p2进行unset操作 unset($t->p1); unset($t->p2); echo "不存在的属性p1的值为:".$t->p1."<br/>"; echo "不存在的属性p2的值为:".$t->p2."<br/>"; /* 结果: 不可访问的属性p1的值为:1 不可访问的属性p2的值为:属性p2不可访问 bool(true) bool(false) 不可访问的属性p1的值为:属性p1不可访问 不可访问的属性p2的值为:属性p2不可访问 */ ?>
2、方法重载
1)__call()
调用对象的不可访问的方法的时候,会自动调用该方法。
2)__callstatic()
调用类的不可访问的静态方法的时候,会自动调用该方法。
示例:
<?php header("Content-type:text/html;charset = utf-8"); class Test { /* @desc 调用不存在的成员方法的时候,会自动调用该方法 @param $name,方法名 @param $args,方法参数 */ function __call($name,$args){ echo "调用不存在的方法{$name}"; } } $t1 = new Test(); $t1->f1(); echo "<br />"; $t1->f2(); /* 结果: 调用不存在的方法f1 调用不存在的方法f2 */ ?>
实例:利用php的方法重载来实现面向对象中通用的重载,即一个类内多个方法的方法名相同但是参数不同
设计一个打招呼的方法,至少输入一个参数(人名)
输入一个参数,输出:hello,xx;
输入两个参数,输出:hello,xx,yy;
输入三个及以上参数,输出:hello,guys;
<?php header("Content-type:text/html;charset = utf-8"); class Test { /* @desc 调用不存在的成员方法的时候,会自动调用该方法 @param $name,方法名 @param $args,方法参数 */ function __call($name,$args){ if ($name === "sayHello") {//处理未定义方法sayHello $n = count($args); if ($n<1) { trigger_error("There's zero params!!!!"); } else if ($n == 1) { echo "hello,{$args[0]}<br/>"; } else if ($n == 2) { echo "hello,{$args[0]},{$args[1]}<br/>"; } else { echo "hello,guys!<br/>"; } } } } $t1 = new Test(); $t1->sayHello(); $t1->sayHello("Richard"); $t1->sayHello("Maria","Robert"); $t1->sayHello("Maria","Robert","Richard"); /* 结果: Notice: There's zero params!!!! in /Users/xx/xx/xx/xx.php on line 14 hello,Richard hello,Maria,Robert hello,guys! */ ?>