开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第二阶段:PHP 继承——重写 Override】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/712/detail/12693
PHP 继承——重写 Override
内容介绍:
一、目标
二、概念
三、步骤
四、示例
五、小结
一、目标
如果在项目开发中,子类不得不去继承了父类以使用一些相关的代码的书写。如果子类发现父类的某一个方法跟自己的想法有出入,或者说业务有变化该怎么办?这时就需要用到重写 override,所以本节目标就是理解重写的概念,掌握重写的语法和相关的意义。
二、概念
Override 是指子类中定义与父类重名的成员,重名成员就叫重写。
1. 子类可以重写父类任意类成员
(1)属性:直接覆盖,父类对象的属性将不存在。(私有除外,因为私有不能覆盖,私有是带类的。)
注意:公有的是属性名,受保护的后面添加 protect 关键字,私有的需要添加类名,观察打印对象时能观察到。
(2)方法:同时存在。因为方法在类里面,两个类都存在,不可能存在覆盖的问题。
2. 通常重写是子类重写父类的方法,(一般重写方法较多,重写属性较少,因为属性没有必要重写,属性可以重新赋值)用于扩展或者更改某些业务逻辑,这也是方法所擅长的地方。
3. 重写要求:
(1)子类对于成员的控制权不能高于父类:就例如父类为public,那子类就只能是 public,不能将其写成 private,只能权限越来越开放,不能越来越收紧。
(2)子类重写方法时,参数要求要与父类一致,这是在 PHP 高版本中才出现的,在低版本中没有此要求,这要特别注意。
三、步骤
1.让类之间存在继承关系。
2.父类存在方法,但是不满足子类业务要求。
3.子类重写父类方法或者属性。
四、示例
1.子类继承父类,同时子类定义与父类同名的类成员。如果子类里面同样有内容,即子类有子类的属性和同名方法,因为方法应用逻辑不一样,那么此时就存在重写。
#父类
class Human{
public $name = ‘ Human’;
public function show(){
Echo_class_,‘ <br/>' ;
}
}
#子类继承
class Man extends Human{
#定义同名属性
public $name =‘Man’;
#定义父类同名方法
public function show(){
Echo_class_,‘ he1lo world<br/>';
}
}
举个例子来观察,建立03override.PHP 文件夹,将上文的代码复制过来,观察其能否实现对应重写,或者写完之后会存在什么问题。刷新一下可以看到没有任何的语法问题,因为本身不存在任何问题,但是此时要去看看子类对象里会存在哪些东西。
2. 重写父类成员之后,子类只会直接访问子类成员(覆盖)。
# 接上述代码
#实例化子类对象
$m = new Man();
$m-> show(); #输出Human hel1o world
var__dump($m) ; #只有子类属性$name
这里来实例化对象,因为看对象只能看到其属性,关键是属性的数量,以及属性的值,属性 name 的值为 Man,说明子类把父类给覆盖掉了,也就是子类同名属性覆盖父类同名属性。
如果有受保护或者私有的,输入 protected $age=19;然后 private $money=20;子类也有对应的属性和方法,观察子类属性,如果子类 protected $age=1;private $money=2;再查看结果是什么样。打印出来此对象发现里面竟然有四个属性,四个属性分别 Name 公有的,man 说明子类覆盖了父类,Protected age=1,说明子类又覆盖了父类,但 private 两个子类里有 money=2,父类里的 money 也存在,所以说明私有的不会被覆盖,其他的会被覆盖。再看调用方法,使用$m调用 show 方法,点击刷新,发现显示 man hello world,也就是走了子类自己的方法,言外之意子类会调用自己的方法来代替原来调用父类的方法,所以其是相当于它的优先权比父类的高,但是方法并不是消失,还是可以去访问。这是属性和方法重写的概念。
注意:不管是公有和是受保护属性,一旦重写,父类就会不存在,而私有属性不会被覆盖而丢失。
3. 重写的要求
(1)子类重写父类的方法,控制权不能高于父类,即子类可以比父类更开放。
#父类
class Human{
protected function show(){
echo__ class__ ,‘<br/>' ;
}
}
#子类继承
class Man extends Human{
#重写
protected function show(){} #正确
public function show(){} #允许
private function show(){} #错误:控制权比父类更严格
比如父类本身有一个方法是 public 的 show,如果需要把子类的改成 protected,点击刷新,之前代码运行都没问题,一刷新系统显示错误,原因是 Access level to man show,就是访问的级别对于 man里面的 show 方法必须要像父类里面的一样,必须要 public。因为 public 已经是最开放的,再往下所有都是收紧权限,所以只能是 public。如果上面是受保护的,那下面就可以是 public 和受保护的,本质是可以越来越开放,但是不能越来越收紧权限。
(2)PHP 中重写要求子类重写父类方法的时候,必须保证与父类同名方法一致。
#父类
class Human{
protected function show(){
Echo_CLASS_,‘<br/>';
}
}
#子类继承
class Man extends Human{
#重写
public function show(){}
public function show($a){} #错误,与父类同名方法不一致
子类重写父类方法的保障同名方法参数要一致,比如现在发现,复类里有一个方法,或者子类需要传入参数,这里传入参数$a,刷新提示,告诉这时是重新声明了一个方法,这是不行的,因为方法必须要跟父类的方法要保持一致,所以不能有这个参数。而同样的,如果父类规定有参数,这里没有参数,也是不行的,就是这样的逻辑。这是第二个,也就是要求参数必须要一致。
注意:在方法参数要求一致不单单是要求数量一致,而且数据类型也必须相同,但形参名字可以不同,因为形参只是内部使用,这跟是否同名没有关系,但是类型、数量必须要保持一致,不能真正意义上去完全修改,将其变得面目全非,还要按照它的逻辑来。其实新建一个也是可以的,如果发现业务跟其完全不一样、参数也不一样,那就不用父类的方法再写一个也是可以的。在 PHP7以前重写对于参数这块没有要求。
(3)针对的是被继承的成员,父类私有方法不会被继承,因此不要求有上述的两个规定,即发现如果父类的方法是一个私有的,那子类的能不能重写呢?
比如说输写 private function getmoney 这时这个方法就完成了。没参数,甚至没有方法体,下方继续输写 Private function getmoney($m),然后这时需要里面的逻辑,输入$this->money=$money,然后输入 echo $money 将其输出出来发现编译发现根本没问题,即因为私有的是在类里面,其实本质不存在重写的概念,因为方法没办法到里面来进行访问,而其他的方法,本身在类里面就可以访问,受保护的或者公有的本身这里就能访问,但是私有的本身就访问不了,所以不可能冲突。这就是私有的,这里面还有细节就是:注意私有方法本质说不存在重写的概念,既然不存在,那写什么都是正确的,所有的规则都不存在,都不生效。
五、示例
1.重写 override 是一种在子类中定义父类同名成员的操作
2.公有、受保护的属性重写是直接覆盖父类成员,私有属性不会被覆盖;公有、收保护的方法会被重写,但是私有方法不会被重写(私有方法本质没有被继承)
3.重写的要求
(1)子类控制权不能高于父类控制权(例如父类规定可以面向公众的方法,子类没有此方法,变成私有,这是不行的)。
(2)PHP7中要求被重写的方法必须与父类保持参数一致(数量和类型)。
(3)私有方法不能继承,因此不存在重写。
4.静态成员也可以被重写,但是静态属性不会被覆盖(属于类,不属于对象)。
最后要强调的一点是重写最重要的目的是父类已经做好的事情,不能满足子类的需求,这个时候需要使用重写。