W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
PHP所提供的重載(overloading)是指動態(tài)地創(chuàng)建類屬性和方法。我們是通過魔術方法(magic methods)來實現(xiàn)的。
當調(diào)用當前環(huán)境下未定義或不可見的類屬性或方法時,重載方法會被調(diào)用。本節(jié)后面將使用不可訪問屬性(inaccessible properties)和不可訪問方法(inaccessible methods)來稱呼這些未定義或不可見的類屬性或方法。
所有的重載方法都必須被聲明為 public。
注意:這些魔術方法的參數(shù)都不能通過引用傳遞。
注意:PHP中的重載與其它絕大多數(shù)面向?qū)ο笳Z言不同。傳統(tǒng)的重載是用于提供多個同名的類方法,但各方法的參數(shù)類型和個數(shù)不同。
public __set(string $name, mixed $value): void
public __get(string $name): mixed
public __isset(string $name): bool
public __unset(string $name): void
在給不可訪問(protected 或 private)或不存在的屬性賦值時,__set() 會被調(diào)用。
讀取不可訪問(protected 或 private)或不存在的屬性的值時,__get() 會被調(diào)用。
當對不可訪問(protected 或 private)或不存在的屬性調(diào)用 isset() 或 empty() 時,__isset() 會被調(diào)用。
當對不可訪問(protected 或 private)或不存在的屬性調(diào)用 unset() 時,__unset() 會被調(diào)用。
參數(shù) ?$name
? 是指要操作的變量名稱。__set() 方法的 ?$value
? 參數(shù)指定了 ?$name
? 變量的值。
屬性重載只能在對象中進行。在靜態(tài)方法中,這些魔術方法將不會被調(diào)用。所以這些方法都不能被 聲明為 static。將這些魔術方法定義為 static 會產(chǎn)生一個警告。
注意:因為 PHP 處理賦值運算的方式,__set() 的返回值將被忽略。類似的, 在下面這樣的鏈式賦值中,__get() 不會被調(diào)用: $a = $obj->b = 8;
注意:PHP 不會在重載方法中再次調(diào)用本身。這意味著如果沒有定義 foo 屬性,在 __get() 中執(zhí)行 return $this->foo 將會返回 null 并引發(fā) E_WARNING,而不是再次調(diào)用 __get()。然而,重載方法可能會隱式調(diào)用其它重載方法(比如調(diào)用 __set() 觸發(fā) __get())。
示例 #1 使用 __get(),__set(),__isset() 和 __unset() 進行屬性重載
<?php
class PropertyTest {
/** 被重載的數(shù)據(jù)保存在此 */
private $data = array();
/** 重載不能被用在已經(jīng)定義的屬性 */
public $declared = 1;
/** 只有從類外部訪問這個屬性時,重載才會發(fā)生 */
private $hidden = 2;
public function __set($name, $value)
{
echo "Setting '$name' to '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Getting '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Undefined property via __get(): ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
public function __isset($name)
{
echo "Is '$name' set?\n";
return isset($this->data[$name]);
}
public function __unset($name)
{
echo "Unsetting '$name'\n";
unset($this->data[$name]);
}
/** 非魔術方法 */
public function getHidden()
{
return $this->hidden;
}
}
echo "<pre>\n";
$obj = new PropertyTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
echo $obj->declared . "\n\n";
echo "Let's experiment with the private property named 'hidden':\n";
echo "Privates are visible inside the class, so __get() not used...\n";
echo $obj->getHidden() . "\n";
echo "Privates not visible outside of class, so __get() is used...\n";
echo $obj->hidden . "\n";
?>
以上示例會輸出:
Setting 'a' to '1'
Getting 'a'
1
Is 'a' set?
bool(true)
Unsetting 'a'
Is 'a' set?
bool(false)
1
Let's experiment with the private property named 'hidden':
Privates are visible inside the class, so __get() not used...
2
Privates not visible outside of class, so __get() is used...
Getting 'hidden'
Notice: Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29
public __call(string $name, array $arguments): mixed
public static __callStatic(string $name, array $arguments): mixed
在對象中調(diào)用一個不可訪問方法時,__call() 會被調(diào)用。
在靜態(tài)上下文中調(diào)用一個不可訪問方法時,__callStatic() 會被調(diào)用。
$name 參數(shù)是要調(diào)用的方法名稱。$arguments 參數(shù)是一個枚舉數(shù)組,包含著要傳遞給方法 $name 的參數(shù)。
示例 #2 使用 __call() 和 __callStatic() 對方法重載
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// 注意: $name 的值區(qū)分大小寫
echo "Calling object method '$name' "
. implode(', ', $arguments). "\n";
}
public static function __callStatic($name, $arguments)
{
// 注意: $name 的值區(qū)分大小寫
echo "Calling static method '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('in object context');
MethodTest::runTest('in static context');
?>
以上示例會輸出:
Calling object method 'runTest' in object context
Calling static method 'runTest' in static context
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: