如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重载。
当对父类的方法进行重写时,子类中的方法必须和父类中对应的方法具有相同的方法名称,在PHP5中不限制输入参数类型、参数数量和返回值类型。(这点和Java不同)。
子类中的覆盖方法不能使用比父类中被覆盖方法更严格的访问权限。
声明方法时,如果不定义访问权限。默认权限为public。
PHP5重写方法
先设置一个父类,这个父类是 “Dog”类,这个类描述了dog的特性。
Dog有2个眼睛,会跑,会叫。就这样描述先。
我养了一直狗,是只小狗,符合Dog类的特性,但有所不同。
我的小狗有名字,我的小狗太小了,不会大声的叫,只会哼哼。
我们用继承的概念去实现这个设计。
1 <? 2 // 狗有两只眼睛,会汪汪叫,会跑. 3 class Dog { 4 protected $eyeNumber =2; //属性 5 //返回封装属性的方法. 6 public function getEyeNumber(){ 7 return $this->eyeNumber; 8 } 9 //狗会叫 10 public function yaff(){ 11 return "Dog yaff, wang ..wang .."; 12 } 13 //狗会跑 14 public function run(){ 15 return "Dog run..running ..."; 16 } 17 } 18 $dog = new Dog(); 19 echo "dog have ".$dog->getEyeNumber()." eyes. <br>"; 20 echo $dog->yaff() ."<br>".$dog->run(); 21 echo "<br><br>"; 22 //这是我的小狗叫"狗狗",它很小.不会汪汪叫,只会哼哼哼.. 23 class MyDog extends Dog { 24 private $name = "狗狗"; 25 public function getName(){ 26 return $this->name; 27 } 28 public function yaff(){ 29 return $this->name." yaff, heng...heng .."; 30 } 31 } 32 $myDog = new MyDog(); 33 echo $myDog->getName()." have ".$myDog->getEyeNumber()." eyes. <br>"; 34 echo $myDog->yaff() ."<br>".$myDog->run(); 35 ?>
程序运行结果:
dog have 2 eyes. Dog yaff, wang ..wang .. Dog run..running ... 狗狗 have 2 eyes. 狗狗 yaff, heng...heng .. Dog run..running ...
重写方法与访问权限
子类中的覆盖方法不能使用比父类中被覆盖方法更严格的访问权限。
父类为public 子类为 private时。
1 <? 2 // 简化dog类和mydog类,演示重写的访问权限. 3 class Dog { 4 protected $eyeNumber =2; //属性 5 //返回封装属性的方法. 6 public function getEyeNumber(){ 7 return $this->eyeNumber; 8 } 9 } 10 class MyDog extends Dog { 11 protected function getEyeNumber(){ 12 return $this->eyeNumber; 13 } 14 } 15 /* 16 class MyDog extends Dog { 17 private function getEyeNumber(){ 18 return $this->eyeNumber; 19 } 20 } 21 */ 22 ?>
程序运行结果:
Fatal error: Access level to MyDog::getEyeNumber() must be public (as in class Dog) in E:PHPProjects est.php on line *
父类为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 est.php on line *
重写时的参数数量
子类可以拥有与父类不同的参数数量。(这点与java不同,PHP是弱类型语言。)
1 <? 2 // 简化dog类和mydog类,演示重写方法的参数. 3 class Dog { 4 protected $eyeNumber =2; //属性 5 //返回封装属性的方法. 6 public function getEyeNumber(){ 7 return $this->eyeNumber; 8 } 9 } 10 class MyDog extends Dog { 11 //重写的方法与父类的方法有不同的参数数量. 12 public function getEyeNumber($eys){ 13 $this->eyeNumber = $eys; 14 return $this->eyeNumber; 15 } 16 } 17 $myDog = new MyDog(); 18 echo "my dog hava ".$myDog->getEyeNumber(3) ." eyes."; 19 //啸天犬..哈.. 20 //下面这句会报一个丢失参数的错误. 21 //echo "my dog hava ".$myDog->getEyeNumber() ." eyes."; 22 ?>
程序运行结果:
1 my dog hava 3 eyes.
构造函数重写
下面这个例子中,父类和子类都有自己的构造函数,当子类被实例化时,子类的构造函数被调用,而父类的构造函数没有被调用,请对比第一节的构造函数继承。
1 <? 2 //2-2 / extends1.php 3 //构造函数继承的问题. 4 class Animal{ 5 public $legNum = 0; 6 public function __construct(){ 7 $this->legNum = 4; 8 echo "I am an animal<br>"; 9 } 10 } 11 class Dog1 extends Animal { 12 public function __construct(){ 13 $this->legNum = 4; 14 echo "I am a Dog .<br>"; 15 } 16 } 17 $dog1 = new Dog1(); 18 echo "<br>"; 19 echo "legNum is ".$dog1->legNum; 20 /* 21 实例化子类时.构造函数被调用了. 22 */ 23 ?>
程序运行结果:
1 I am a Dog . 2 legNum is 4
注:这点和Java不同,在java中构造函数是不能被继承的,而且子类实例化时,子类的构造函数被调用,父类的构造函数也会调用。