PHP中的」重載」與其它絕大多數物件導向語言不同,只是他們都是用的相同的名詞而已。傳統的」重載」是用來提供多個同名的 類別方法,但各方法的參數類型和個數不同。 PHP所提供的”重載”(overloading)是指動態地”創建”類別屬性和方法。當呼叫目前環境下未定義或不可見#的類別屬性或方法時,重載方法會被呼叫。是透過魔術方法(magic methods)來實現的。
一般來說,把類別中的成員屬性都定義為private的,這更符合現實的邏輯,能夠更好的對類別中成員起到保護作用。但是,對成員屬性的讀取和賦值操作是非常頻繁的,而如果在類別中為每個私有屬性定義可以在物件的外部取得和賦值的公有方法,又是非常非常煩惱的。因此在PHP5.1.0以後的版本中,預先定義了兩個方法“get()”和“set()”,用來完成對所用私有屬性都能取得和賦值操作,以及用來檢查私有屬性是否存在的方法「isset()」和用來刪除物件中私有屬性方法「unset()」。
通俗一點來說,重載在php中的意義是指,當一個物件或類別使用其未定義或不可見的屬性和方法時,其中的一些「處理機制」。
對一個物件不存在的屬性進行使用時,這個類別中預先設定好的應對辦法(處理機制)。
屬性,本質就是變數,其只有4個運算:
當對當一個物件不存在(未定義或不可見)的屬性進行「取值」時,就會自動呼叫方法:GET() 方法不區分大小寫。
當對一個物件不存在(未定義或不可見)的屬性進行「賦值」時,就會自動呼叫方法:SET()
# 當對一個物件不存在(未定義或不可見)的屬性進行isset()判斷時,就會自動呼叫方法:isset()
當對一個物件不存在的(未定義或不可見)屬性進行unset()判斷時,就會自動呼叫方法:unset()
以上4個方法,稱為魔術方法。
在對一個物件不存在的屬性進行「取值」的時候,會自動呼叫的方法,其中該方法可以帶一個形參,表示要對之取值而又不存在的屬性名(字符串),可以使用此方法對意外情況進行某種特殊的處理。
例如:
<?phpclass A{ public $p1 = 1; }$a1 = new A();echo $a1->p1; //1echo $a1->p2; //未定义$p2,会报错, Notice: Undefined property: A::$p2?>
php的重載,使用get()方法對上面的出錯作「優雅處理」。
<?php<?phpclass A{ public $p1 = 1; //private $p2 = 1; //这里将属性私有化,其实和未定义一样,对外部来说都相当于不存在 function get($prop_name){ /* //比如可以这样处理 echo "<br />{$prop_name}属性还未定义(不存在)!"; return ""; //也可以返回0,或false等 */ //还可以这样处理 trigger_error("发生错误:属性不存在!", E_USER_ERROR); die(); } }$a1 = new A();echo $a1->p1; //1echo $a1->p2; //未定义$p2,但经过"处理"?>
這裡舉一個對所用私有屬性所取得的操作的例子。
範例:
<?phpclass Person{ public $name; public $sex; private $age; //年龄私有化,类外不能直接访问这个属性 function construct($name='', $sex='', $age){ $this->name = $name; $this->sex = $sex; $this->age = $age; } private function get($propertyName){ //这里要用private修饰,防止类外部调用 if($propertyName == 'age'){ return $this->age; } } }$p = new Person('yeoman', '男',23); $v1 = $p->name;$v2 = $p->sex;$v3 = $p->age; //自动调用了get()方法获取私有属性age(函数定义里面返回) echo "name=$v1, sex=$v2, age=$v3";?>
運行結果為:
name=yeoman, sex=男, age=23
# 當對一個物件不存在的屬性進行「賦值」時,就會自動呼叫這個內部的魔術方法;其有2個形參,分別代表要對不存在的屬性進行賦值的「屬性名稱」和“屬性值”。
這個方法,結合_GET方法,往往可以使我們定義的類,有一種可擴展的特性。即:類別或物件的屬性,可以更為方便自由。
範例:
<?phpclass A{ //定义一个属性, protected $prop_list = array(); //初始为空数组 //这个方法会在A的对象使用一个不存在的属性进行赋值时调用 function set($p,$v){ //echo "使用不存在的属性!"; $this->prop_list[$p] = $v; } function get($p){ return $this->prop_list[$p]; } }$a1 = new A();$a1->p1 = 1; //不存在的属性名赋值,此时会调用_set(),并传过去"p1"和1$a1->p2 = 2;$a1->ac = 'avc'; echo "<br />输出这些“不存在的属性”的值:"; echo "<br />a1->p1:" . $a1->p1; //不存在的属性名取值,此时会调用_get(),并传过去"p1"echo "<br />a1->p2:" . $a1->p2;echo "<br />a1->ac:" . $a1->ac;?>
運行結果為:
输出这些“不存在的属性”的值:a1->p1:1a1->p2:2a1->ac:avc
當對一個物件不存在的屬性進行isset()判斷時,就會自動呼叫內部方法:isset();
用法:
$v1 = isset($对象->不存在的属性); //此时会调用这个对象所属类中的魔术方法:isset()
範例:
<?phpclass A{ //定义一个属性, protected $prop_list = array(); //初始为空数组 //这个方法会在A的对象使用一个不存在的属性进行赋值时调用 function set($p,$v){ //echo "使用不存在的属性!"; $this->prop_list[$p] = $v; } function get($p){ if($this->prop_list[$p]){ return $this->prop_list[$p]; }else{ return "该属性不存在!"; } } function isset($prop){ //isset()是自定义的方法, isset()是系统函数 $re = isset($this->prop_list[$prop]); return $re; } } $a1 = new A(); $a1->p1 = 1;//不存在的属性名赋值,此时会调用_set(),并传过去"p1"和1 $a1->p2 = 2; $a1->ac = 'avc'; echo "<br />输出这些“不存在的属性”的值"; echo "<br />a1->p1:" . $a1->p1;//不存在的属性名取值,此时会调用_get(),并传过去"p1" echo "<br />a1->p2:" . $a1->p2; echo "<br />a1->ac:" . $a1->ac; //下面演示isset判断不存在的属性 $v1 = isset($a1->p1); //存在 $v2 = isset($a1->ppp1); //不存在 var_dump($v1);echo "<br />"; var_dump($v2);?>
運行結果:
输出这些“不存在的属性”的值 a1->p1:1a1->p2:2a1->ac:avc boolean trueboolean false
當對一個物件不存在的屬性進行unset()銷毀時,就會自動呼叫內部方法:unset();
<?phpclass A{ //定义一个属性, protected $prop_list = array(); //初始为空数组 //这个方法会在A的对象使用一个不存在的属性进行赋值时调用 function set($p,$v){ //echo "使用不存在的属性!"; $this->prop_list[$p] = $v; } function get($p){ if($this->prop_list[$p]){ return $this->prop_list[$p]; }else{ return "该属性不存在!"; } } function unset($prop){ unset($this->prop_list[$prop]); } }$a1 = new A(); $a1->p1 = 1;//不存在的属性名赋值,此时会调用_set(),并传过去"p1"和1 echo "<br />a1->p1:" . $a1->p1;//不存在的属性名取值,此时会调用_get(),并传过去"p1"//下面演示unset销毁一个不存在的属性 unset($a1->p1); echo "<br />a1->p1:" . $a1->p1;?>
運行結果為:
a1->p1:1a1->p1:该属性不存在!
下面的範例中,宣告一個Person類,並將所有的成員屬性設為private的。在類別中加入自訂的「isset()」和「unset()」兩個方法。在類別外部使用「isset()」和「unset()」函數時,會自動呼叫這兩個方法。程式碼如下:
<?php class Person{ private $name; //此属性被封住 private $sex; private $age; function __construct($name='', $sex='男', $age){ $this->name = $name; $this->sex = $sex; $this->age = $age; } private function __isset($propertyName){ //需要一个参数,是测定的私有属性的名称 if($propertyName == 'name'){ return false; //返回假,不允许在类外部测定name属性 } return isset($this->$propertyName); //这里propertyName要加$符,因为这是参数,不是属性 } private function __unset($propertyName){ if($propertyName == 'name') return; //退出方法,不允许删除对象中的name属性 unset($this->$propertyName); //这里propertyName要加$符 } public function say(){ echo "名字:" . $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age . "<br />"; } } $person = new Person("yeoman", "男", 23); var_dump(isset($person->name)); //输出bool(false),不允许测定name属性 var_dump(isset($person->sex)); //输出bool(true),存在sex私有属性 var_dump(isset($person->age)); //输出bool(true),存在age私有属性 var_dump(isset($person->id)); //输出bool(false),测定对象中不存在id属性 unset($person->name); //删除私有属性name,但在 __unset()中不允许删除 unset($person->sex); //删除对象中的私有属性sex,删除成功 unset($person->age); $person->say(); //对象中的sex和age属性被删除,输出:名字:yeoman,性别:,年龄: ?>
運行結果:
boolean falseboolean trueboolean trueboolean false名字:yeoman,性别:,年龄:
当对一个对象不存在的实例方法进行“调用”时,会自动调用类中的call()这个魔术方法;
当对一个类不存在的静态方法进行“调用”时,会自动调用类中的callstatic()这个魔术方法。
例子:直接调用不存在的方法
<?phpini_set('display_errors',1);class A{}$a = new A();$a->f1(); //不存在的方法?>
会报错,报错内容为:
Fatal error: Uncaught Error: Call to undefined method A::f1()
对上面报错作“优雅处理”:
<?phpclass A{ //当对这个类的对象不存在的实力方法进行调用时,会自动调用本方法 //这个方法必须带2个形参: //$methodName:表示要调用的不存在的方法名; //$argument:表示要调用该不存在的方法时,所使用的实参数据,是一个数组。 function call($methodName, $argument){ //echo "call被调用了!"; echo $methodName . "()方法不存在!"; } }$a = new A();$a->f1(); //不存在的方法,但经过处理?>
运行结果为:
f1()方法不存在!
当对一个类不存在的静态方法进行“调用”时,会自动调用类中的callstatic()这个魔术方法。和上面的处理类似。
以上是PHP物件導向-詳細介紹重載(overloading)的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!