如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆寫(override),也稱為方法的重載。
當對父類的方法進行重寫時,子類中的方法必須和父類中對應的方法具有相同的方法名稱,在PHP5中不限制輸入參數類型、參數數量和傳回值類型。(這點和Java不同)。
子類中的覆寫方法不能使用比父類中被覆寫方法更嚴格的通路權限。
聲明方法時,如果不定義通路權限。預設權限為public。
PHP5重寫方法
先設定一個父類,這個父類是 “Dog”類,這個類描述了dog的特性。
Dog有2個眼睛,會跑,會叫。就這樣描述先。
我養了一直狗,是隻小狗,符合Dog類的特性,但有所不同。
我的小狗有名字,我的小狗太小了,不會大聲的叫,隻會哼哼。
我們用繼承的概念去實作這個設計。
// 狗有兩隻眼睛,會汪汪叫,會跑.
class Dog {
protected $eyeNumber =2; //屬性
//傳回封裝屬性的方法.
public function getEyeNumber(){
return $this->eyeNumber;
}
//狗會叫
public function yaff(){
return "Dog yaff, wang ..wang ..";
}
//狗會跑
public function run(){
return "Dog run..running ...";
}
}
$dog = new Dog();
echo "dog have ".$dog->getEyeNumber()." eyes.
";
echo $dog->yaff() ."
".$dog->run();
echo "
";
//這是我的小狗叫"狗狗",它很小.不會汪汪叫,隻會哼哼哼..
class MyDog extends Dog {
private $name = "狗狗";
public function getName(){
return $this->name;
}
public function yaff(){
return $this->name." yaff, heng...heng ..";
}
}
$myDog = new MyDog();
echo $myDog->getName()." have ".$myDog->getEyeNumber()." eyes.
";
echo $myDog->yaff() ."
".$myDog->run();
?>
程式運作結果:
dog have 2 eyes.
Dog yaff, wang ..wang ..
Dog run..running ...
狗狗 have 2 eyes.
狗狗 yaff, heng...heng ..
Dog run..running ...
重寫方法與通路權限
子類中的覆寫方法不能使用比父類中被覆寫方法更嚴格的通路權限。
父類為public 子類為 private時。
// 簡化dog類和mydog類,示範重寫的通路權限.
class Dog {
protected $eyeNumber =2; //屬性
//傳回封裝屬性的方法.
public function getEyeNumber(){
return $this->eyeNumber;
}
}
class MyDog extends Dog {
protected function getEyeNumber(){
return $this->eyeNumber;
}
}
?>
程式運作結果:
Fatal error: Access level to MyDog::getEyeNumber() must be public (as in class Dog) in E:\PHPProjects\test.php on line 15
父類為public 子類為 protected時。
// 簡化dog類和mydog類,示範重寫的通路權限.
class Dog {
protected $eyeNumber =2; //屬性
//傳回封裝屬性的方法.
public function getEyeNumber(){
return $this->eyeNumber;
}
}
class MyDog extends Dog {
private function getEyeNumber(){
return $this->eyeNumber;
}
}
?>
程式運作結果:
Fatal error: Access level to MyDog::getEyeNumber() must be public (as in class Dog) in E:\PHPProjects\test.php on line 15
重寫時的參數數量
子類可以擁有與父類不同的參數數量。(這點與java不同,PHP是弱類型語言。)
// 簡化dog類和mydog類,示範重寫方法的參數.
class Dog {
protected $eyeNumber =2; //屬性
//傳回封裝屬性的方法.
public function getEyeNumber(){
return $this->eyeNumber;
}
}
class MyDog extends Dog {
//重寫的方法與父類的方法有不同的參數數量.
public function getEyeNumber($eys){
$this->eyeNumber = $eys;
return $this->eyeNumber;
}
}
$myDog = new MyDog();
echo "my dog hava ".$myDog->getEyeNumber(3) ." eyes.";
//嘯天犬..哈..
//下面這句會報一個丢失參數的錯誤.
//echo "my dog hava ".$myDog->getEyeNumber() ." eyes.";
?>
程式運作結果:
my dog hava 3 eyes.
構造函數重寫
下面這個例子中,父類和子類都有自己的構造函數,當子類被執行個體化時,子類的構造函數被調用,而父類的構造函數沒有被調用,請對比第一節的構造函數繼承。
//2-2 / extends1.php
//構造函數繼承的問題.
class Animal{
public $legNum = 0;
public function __construct(){
$this->legNum = 4;
echo "I am an animal
";
}
}
class Dog1 extends Animal {
public function __construct(){
$this->legNum = 4;
echo "I am a Dog .
";
}
}
$dog1 = new Dog1();
echo "
";
echo "legNum is ".$dog1->legNum;
?>
程式運作結果:
I am a Dog .
legNum is 4
注:這點和Java不同,在java中構造函數是不能被繼承的,而且子類執行個體化時,子類的構造函數被調用,父類的構造函數也會調用。
延伸閱讀
此文章所在專題清單如下: