如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(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;
}
}
/*
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
父类为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中构造函数是不能被继承的,而且子类实例化时,子类的构造函数被调用,父类的构造函数也会调用。
延伸阅读此文章所在专题列表如下:
PHP面向对象之旅:类和对象
PHP面向对象之旅:类的属性
PHP面向对象之旅:类的方法
PHP面向对象之旅:对象的比较
PHP面向对象之旅:构造函数
PHP面向对象之旅:类的继承
PHP面向对象之旅:访问控制
PHP面向对象之旅:方法覆盖
PHP面向对象之旅:this关键字
PHP面向对象之旅:parent::关键字
PHP面向对象之旅:再谈重载
PHP面向对象之旅:获取用户数据
PHP面向对象之旅:用户权限管理类
PHP面向对象之旅:static变量与方法
PHP面向对象之旅:单例模式
PHP面向对象之旅:final类和方法
PHP面向对象之旅:PHP中的常量
PHP面向对象之旅:抽象类
PHP面向对象之旅:抽象方法
PHP面向对象之旅:抽象类继承抽象类
PHP面向对象之旅:静态抽象方法
PHP面向对象之旅:模板模式
PHP面向对象之旅:接口与抽象方法
PHP面向对象之旅:接口的实现
PHP面向对象之旅:接口的继承
PHP面向对象之旅:类型提示
PHP面向对象之旅:PHP的多态
PHP面向对象之旅:instanceof运算符
PHP面向对象之旅:接口与组合模拟多继承
PHP面向对象之旅:一个接口实例
PHP面向对象之旅:简单工厂模式