PHP所提供的"重載"(overloading)是指動態地"建立"類別屬性和方法。我們是透過魔術方法(magic methods)來實現的。
當呼叫目前環境下未定義或不可見的類別屬性或方法時,重載方法會被呼叫。
所有的重載方法都必須宣告為 public。
注意:
1)這些魔術方法的參數都不能透過引用傳遞。
2)PHP中的"重載"與其它絕大多數物件導向語言不同。傳統的"重載"是用來提供多個同名的類別方法,但各方法的參數類型和個數不同。
屬性重載
public void__set(string$name, mixed$value) publicmixed__get(string$name) publicbool__isset(string$name) publicvoid__unset(string$name)
在賦值不可存取屬性時,__set() 會被呼叫。
讀取不可存取屬性的值時,__get() 會被呼叫。
當對不可存取屬性呼叫 isset() 或 empty() 時,__isset() 會被呼叫。
當對不可存取屬性呼叫 unset() 時,__unset() 會被呼叫。
參數 $name 是指要操作的變數名稱。 __set() 方法的 $value 參數指定了 $name 變數的值。
屬性重載只能在物件中進行。在靜態方法中,這些魔術方法將不會被呼叫。所以這些方法都不能被 宣告為 static。從 PHP 5.3.0 起, 將這些魔術方法定義為 static 會產生一個警告。
注意:
因為 PHP 處理賦值運算的方式,__set() 的回傳值會被忽略。類似的, 在下面這樣的鍊式賦值中,__get() 不會被調用:
$a = $obj->b = 8;
注意:
在除 isset() 外的其它語言結構中無法使用重載的屬性,這表示當對一個重載的屬性使用 empty() 時,重載魔術方法將不會被呼叫。
為避開此限制,必須將重載屬性賦值到本地變數再使用 empty()。
Example #1 使用 __get(),__set(),__isset() 和 __unset() 進行屬性重載
class PropertyTest{ /*被重载的数据保存在此*/ private $data = array(); /*重载不能被用在已经定义的属性*/ public $declared = 1; /*只有从类外部访问这个属性时,重载才会发生*/ private $hidden = 2; public function __set($name,$value) { echo "Setting '$name' to '$value'<br>"; $this->data[$name] = $value; } public function __get($name) { echo "Getting '$name'<br>"; if(array_key_exists($name,$this->data)){ return $this->data[$name]; } $trace = debug_backtrace(); trigger_error('未知属性 via __get():'.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE); return null; } /*PHP5.1.0之后的版本*/ public function __isset($name){ echo "Is '$name' set?<br>"; return isset($this->data[$name]); } /*PHP5.1.0之后的版本*/ public function __unset($name){ echo "Unsetting '$name'<br>"; unset($this->data[$name]); } /*非魔术方法*/ public function getHidden(){ return $this->hidden; } } echo '<pre class="brush:php;toolbar:false">'; $obj = new PropertyTest; $obj->a = 1; echo $obj->a.'<br>'; var_dump(isset($obj->a)); unset($obj->a); echo '<br>'; echo $obj->declared.'<br>'; echo "Let's experiment with the private property named 'hidden':<br>"; echo "Privates are visible inside the class,so __set() not used...<br>"; echo $obj->getHidden().'<br>'; echo "Privates not visible outside of class,so __get() is used...<br>"; echo $obj->hidden;
輸出結果:
Setting 'a' to '1'
Is 'a' set?bool(true)Unsetting 'a'
1
) iniv. ...
2
Privates not visible outside of class,so __get() is used...
Getting 'hidden'
方法重載
public mixed __call ( string$name , array$arguments ) public static mixed __callStatic ( string$name , array$arguments )
在物件中使用一個不可存取方法時,__call(__在物件中) 會被呼叫。
用靜態方式中呼叫一個不可存取方法時,__callStatic() 會被呼叫。
$name 參數是要呼叫的方法名稱。 $arguments 參數是一個枚舉數組,包含著要傳遞給方法 $name 的參數。
Example #2 使用 __call() 和 __callStatic() 對方法重載
class MethodTest { public function __call($name,$arguments) { //注意:$name的值区分大小写 echo "Calling object method '$name' ".implode(',',$argument).'<br>'; } //PHP5.3.0之后的版本 public static function __callStatic($name,$arguments) { //注意:$name的值区分大小写 echo "Calling static method '$name' ".implode(',',$argument).'<br>'; } } $obj = new MethodTest; $obj -> runTest('in object context'); MethodTest::runTest('in static context');
輸出結果:
Calling object method 'runTest'
Calling object method 'runTest'