因為在PHP中不能存在同名的函數,所以在同一個類中也就不能定義重名的方法。這裡所說的重載是指在 子類中可以定義和父類同名的方法從而覆蓋從父類中繼承過來的方法。
子類中重載父類的方法
<?php
class Person{
public $name;
public function __construct($name="" ){
$this->name =$name;
}
public function say(){
echo "我叫".$this->name ;
}
}
?>
<?php
class Student extends Person{
public $name;
public function __construct($name=""){
$this->name =$name;
}
//這裡定義了一個和父類中同名的方法,將父類中的說話方法覆蓋並重寫
public function say(){
echo "我叫".$this->name .",今年25歲了" ;
}
}
?>
重寫方法與訪問權限
子類中的覆蓋方法不能使用比父類中被覆蓋方法更嚴格的訪問權限。
如果父類中的方法的訪問權限是protected,那麼子類中重寫的方法的權限就要是protected或者public; 如果父類中的方法是public,那麼子類要重寫的方法的權限就只能是public。也許這也就是為什麼子類可 以繼承父類的私有成員,但卻不能使用的原因吧。
重寫時的參數數量
子類可以擁有與父類不同的參數數量,如下面的構造方法中,多添加了一個參數$age。
代碼如下 復制代碼<?php
class Student extends Person{
public $name;
public $age;
public function __construct($name="",$age=25){
$this->name =$name;
$this->age =$age;
}
public function say(){
echo "我叫".$this->name .",今年".$this->age."歲了" ;
}
}
?>
構造函數重寫
上面提到的“重寫時的參數數量”就已經實現了子類對父類的構造函數進行了重寫,但這不是一種好的寫 法,如果仔細觀察,你會發現,上面子類Student對父類Person構造函數的重寫,其實就是在父類的構造 函數的基礎上多添加了一個參數,但是又把父類原有的參數照寫一遍,因為父類Person的構造函數只有一 個參數,所以我們照寫一遍不覺得有什麼麻煩,但是如果參數不止一個,而是幾個或者更多,那麼你就會 發現它的繁瑣之處,那麼有沒有辦法可以簡化這個問題呢?答案是肯定的,可通過使用"parent::方法名" 在子類的重載方法中調用父類中被它覆蓋的方法。如使用"parent::__construct()"調用父類中被覆蓋的 構造方法,其它方法的類似,於是上面的代碼可以簡化為:
代碼如下 復制代碼<?php
class Student extends Person{
public $name;
public $age;
public function __construct($name="",$age=25){
parent::__construct($name,$age);
$this->age =$age;
}
public function say(){
parent::say();
echo ",今年".$this->age."歲了" ;
}
}
?>
下再看一個實例
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. <br>";
echo $dog->yaff() ."<br>".$dog->run();
echo "<br><br>";
//這是我的小狗叫"狗狗",它很小.不會汪汪叫,只會哼哼哼..
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. <br>";
echo $myDog->yaff() ."<br>".$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;
}
}
/*
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:PHPProjectstest.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:PHPProjectstest.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<br>";
}
}
class Dog1 extends Animal {
public function __construct(){
$this->legNum = 4;
echo "I am a Dog .<br>";
}
}
$dog1 = new Dog1();
echo "<br>";
echo "legNum is ".$dog1->legNum;
/*
實例化子類時.構造函數被調用了.
*/
?>
程序運行結果:
I am a Dog .
legNum is 4
注:這點和Java不同,在java中構造函數是不能被繼承的,而且子類實例化時,子類的構造函數被調用,父類的構造函數也會調用。