PHP 中的多載(overloading)跟其他語言的多載不太一樣
但我本身是菜雞工程師,其他程式的多載我沒有概念
只能說過我碰最深的(雖然還是淺),也就是 PHP
根據官網的說法,PHP 的“多載”目的在於
動態創建類(Class)的屬性(Property)還有方法(Method)
方法(Method)與函式(Function)差在哪裡?
這兩個在程式碼中明明都是 function,但為什麼會有方法與函式兩種稱呼呢?
主要差別在,當一個函式放在類別(Class)裡面,這個函式就可以稱為方法
反之,當一個函式沒有放在任何類別中,那麼就是一個單純的函式
PHP 的「多載」提供幾個魔術方法,分別是
__set() 方法是在賦值給不可訪問的屬性時會觸發
什麼是不可訪問的屬性?例如原本類別中沒有設定或是設定成 private 的屬性
以下方的 Code 舉例
<?php
class PropertyTest
{
// 被重載的數據保存在此
public $data = [];
// 只有從類外部訪問這個屬性時,重載才會發生
private $hidden = 2;
public function __set($name, $value)
{
echo '已觸發 __set() 方法,設定 ' . $name . ' 為 ' . $value . PHP_EOL;
$this->data[$name] = $value;
}
}
$obj = new PropertyTest;
// 賦值給 $obj 沒有的屬性
$obj->a = 1;
// 賦值給 $obj 中設定為 private(私有成員)的屬性
$obj->hidden = 2;
print_r($obj->data);
因為 PropertyTest 中沒有設定 $a 屬性,而 $hidden 屬性是設定為私有成員,外部無法訪問
因此嘗試賦值給 $a 與 $hidden 屬性都會觸發 __set() 方法
上述的程式碼的執行結果為
已觸發 __set() 方法,設定 a 為 1
已觸發 __set() 方法,設定 hidden 為 2
Array
(
[a] => 1
[hidden] => 2
)
__get() 方法是在讀取不可訪問的屬性時會被觸發
<?php
class PropertyTest
{
// 重載不能被用在已經定義的屬性
public $declared = '讀取 $declared 這個屬性並不會觸發 __get() 方法';
// 只有從類外部訪問這個屬性時,重載才會发生
private $hidden = 2;
public function __get($name)
{
echo '已觸發 __get() 方法,讀取 ' . $name;
}
}
$obj = new PropertyTest;
echo $obj->declared . PHP_EOL;
echo $obj->a . PHP_EOL;
echo $obj->hidden . PHP_EOL;
上述程式碼的執行結果為
讀取 $declared 這個屬性並不會觸發 __get() 方法
已觸發 __get() 方法,讀取 a
已觸發 __get() 方法,讀取 hidden
__isset() 與 __unset() 方法跟官網一樣放在一起講
當對不可訪問的屬性調用 isset() 或 empty() 時,__isset() 會被調用
當對不可訪問屬性調用 unset() 時,__unset() 會被調用
<?php
class PropertyTest
{
// 被重載的數據保存在此
private $data = ['a' => 1];
public function __isset($name)
{
echo $name . ' 有被設定嗎?' . PHP_EOL;
return isset($this->data[$name]);
}
public function __unset($name)
{
echo '將 ' . $name . ' 改成未設定' . PHP_EOL;
unset($this->data[$name]);
}
}
$obj = new PropertyTest;
var_dump(isset($obj->a));
echo PHP_EOL;
unset($obj->a);
echo PHP_EOL;
var_dump(isset($obj->a));
上述程式碼的執行結果為
a 有被設定嗎?
bool(true)
將 a 改成未設定
a 有被設定嗎?
bool(false)
參考資料
Overloading - Manual - PHP
逐步提昇PHP技術能力 - PHP的語言特性 : 多載 (overloading)