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