在java中,重載就是函數或者方法有相同的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之爲重載函數或者方法,這也牽涉到了多態。
在PHP中呢,有人說php沒有多態,那重載呢?
PHP所提供的"重載"(overloading)是指動態地"創建"類屬性和方法,分爲屬性的重載和方法的重載;
我們是通過魔術方法(magic methods)來實現的,當調用當前環境下未定義或不可見的類屬性或方法時,重載方法會被調用。本節後面將使用"不可訪問屬性(inaccessible properties)"和"不可訪問方法(inaccessible methods)"來稱呼這些未定義或不可見的類屬性或方法。
屬性重載
public void __set ( string $name , mixed $value )
public mixed __get ( string $name )
public bool __isset ( string $name )
public void __unset ( string $name )
在給不可訪問的屬性賦值時,__set() 會被調用。
讀取不可訪問的屬性的值時,__get()會被調用。
當判斷不可訪問的屬性是否存在的時候(使用isset(),empty())時,__isset()會被調用。
當對不可訪問的屬性執行銷燬操作(unset())的時候,__unset()會被調用。
__get()方法,有兩個參數,$name是指要操作的變量名稱(另外三個都是這個意思),$value是指對應name的值。
一個很簡單的例子:
class Person {
public $name;
private $age;
public function __set($name, $value)
{
echo "你賦值的屬性{$name}不存在";
}
public function __get($name)
{
echo "你所訪問的屬性{$name}不存在";
}
public function __isset($name)
{
echo "你判斷的屬性{$name}不存在";
}
public function __unset($name)
{
echo "你銷燬的屬性{$name}不存在";
}
}
$person = new Person();
echo '賦值操作:',$person->gender = 'nale',<br />';
echo '取值操作:',$person->gender,'<br />';
echo 'isset判斷操作:',isset($person->gender),'<br />';
echo 'empty判斷操作:',empty($person->gender),'<br />';
echo 'empty判斷操作:',empty($person->gender),'<br />';
echo 'unset操作:';unset($person->gender);
結果如下:
empty這裏後面有個1是因爲當前返回的是true,輸出來就是1了;
當然,大家也會發現,沒有這些魔術方法,我照樣可以跑通,我把這些魔術方法註釋掉:
class Person {
public $name;
private $age;
// public function __set($name, $value)
// {
// echo "你賦值的屬性{$name}不存在";
// }
//
// public function __get($name)
// {
// echo "你所訪問的屬性{$name}不存在";
// }
//
// public function __isset($name)
// {
// echo "你判斷的屬性{$name}不存在";
// }
//
// public function __unset($name)
// {
// echo "你銷燬的屬性{$name}不存在";
// }
//
// public function __call($name, $arguments)
// {
// echo '你在調用不存在的方法';
// }
}
$person = new Person();
echo '賦值操作:',$person->gender = 123,'<br />';
echo '取值操作:',$person->gender,'<br />';
echo 'isset判斷操作:',isset($person->gender),'<br />';
echo 'empty判斷操作:',empty($person->gender),'<br />';
echo 'empty判斷操作:',empty($person->gender),'<br />';
echo 'unset操作:';unset($person->gender);
echo '取值操作:',$person->gender,'<br />'; //訪問不存在的屬性,因爲被銷燬了,應該會報一個notic級別的錯誤
運行如下所示:
這個是因爲在PHP中,並沒有強制屬性都在類中聲明,這是動態的給對象屬性賦值,在其它強類型語言中,可能行不通,所以在一般時候,並不建議這樣寫。
那如果有這種動態增加值的需求的時候怎麼辦呢,我們可以利用屬性的重載來完成,如下:
class Person {
public $name;
private $age;
private $_attr = array();
public function __construct($name,$age)
{
$this->name = $name;
$this->age = $age;
}
public function __get($name)
{
if($this->_attr[$name]){
return $this->_attr[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
$this->_attr[$name] = $value;
}
public function __isset($name)
{
return isset($this->_attr[$name]);
}
public function __unset($name)
{
unset($this->_attr[$name]);
}
}
$person = new Person('lightWay', 24);
//賦值操作
$person->gender = 'male';
$person->home = 'hubei';
echo $person->home; //取值操作
unset($person->home); //銷燬操作
方法重載
public mixed __call ( string $name , array $arguments )
public static mixed __callStatic ( string $name , array $arguments )
在對象中調用一個不可訪問方法時,__call() 會被調用。
在靜態上下文中調用一個不可訪問方法時,__callStatic() 會被調用。
$name 參數是要調用的方法名稱。$arguments 參數是一個枚舉數組,包含着要傳遞給方法 $name 的參數。
上代碼說明吧:
class Person {
public function __call($name, $arguments)
{
echo '您正在調用一個不存在的方法',self::class,'::',$name,PHP_EOL;
print_r($arguments);
}
public static function __callStatic($name, $arguments)
{
echo '您正在調用一個不存在的靜態方法',self::class,'::',$name,PHP_EOL;
print_r($arguments);
}
}
$person = new Person();
$person->sayMyInfo1('123',2,true);
$person::show(1,2,3);
執行結果如下:
我們可以用PHP中的重載,去模擬其他語言中的重載,代碼如下:
class Person {
public $name;
public function __construct($name)
{
$this->name = $name;
}
public function __call($name, $arguments)
{
if($name == 'eating') {
switch (count($arguments)) {
case 1 :
echo "{$this->name}正在用{$arguments[0]}喫中餐",PHP_EOL;
break;
case 2 :
echo "{$this->name}正在用{$arguments[0]}和{$arguments[1]}喫西餐",PHP_EOL;
break;
case 0:
default:
echo "{$this->name}在喝西北風",PHP_EOL;
break;
}
} else {
echo '您訪問的方法不存在';
}
}
}
$my = new Person('lightWay');
$my->eating('筷子');
$my->eating('刀','叉子');
$my->eating();
執行結果如下:
這裏只是用了參數的不同,來執行不同的動作,可以利用的點很多,很多框架都會到這個,好吧,這裏就完了,看完了,你還覺得PHP沒用多態嗎?