在PHP里,什么是抽象类?
抽象类指的是不能被直接实例化的类,它专门用作其他类的基类,用于定义抽象方法(抽象方法指的是通过abstract修饰的方法)和具体方法(有实现的方法)。
抽象类必须用abstract来修饰!值得注意的是,如果一个类至少有一个抽象方法,那么这个类就是抽象类。
比如我们准备一个抽象类People,由于每个人学习、放松、运动、恋爱的方法不同,所以我们可以抽象出四个方法。因为是抽象方法,所以在声明时需要使用abstract关键字来修饰,不需要“{}”来具体指定方法,而是换成“;”结束抽象方法。
<?php
/* 1. 准备一个抽象类 */
abstract class People//2. 抽象类必须通过abstruct关键字来修饰
{
// 3. 如果有一个抽象方法,那么这个类一定是抽象类,以下有4个抽象方法,都没有通过“{}”指明具体方法,而且通过“;”结束抽象语句
abstract public function study();//学习
abstract public function relax();//放松
abstract public function sport();//运动
abstract public function love();//恋爱
}
?>抽象类是为服务于子类而产生的,所以谈论抽象类就离不开继承这个环节。
1. 我们先讨论权限问题(指的是public、protected修饰抽象类时。注意,没有private修饰抽象类):
我们都知道,子类继承父类时,由于父类的访问权限不同,所以子类能够继承的数据是有差异的,具体情况如下:
| 关键字 | 类内部访问 | 子类访问 | 外部访问 |
|---|---|---|---|
| public | √允许 | √ 允许 | √ 允许 |
| protected | √ 允许 | √ 允许 | × 不允许 |
| private | √ 允许 | × 不允许 | × 不允许 |
对于抽象类的继承,我们要求:子类实现方法的权限不能比抽象方法更严格!
比如People类是抽象类,子类是Programmar,抽象类People的抽象方法study()被public修饰,子类的study()就不能被protected修饰;如果抽象类People的抽象方法study()被protected修饰,那么子类的study()既可以使用public修饰,又可以使用protected修饰。这个约束既来自于技术层面(避免运行时访问错误),又来自于默认的里氏替换原则(子类必须替换父类),所以请读者谨记这个契约。
下面,我们通过代码来描述这个约束:
<?php
/* 1. 准备一个抽象类 */
abstract class People
{
/* 抽象方法是服务于子类的,禁止private! */
abstract public function study();//学习
abstract public function relax();//放松
abstract public function sport();//运动
abstract protected function love();//恋爱
}
/* 2.准备一个Programmar类 */
class Programmar extends People
{
/* 必须全部重写父类抽象方法 */
public function study()//由于抽象类的study()是public,所以子类就不能是protected!
{
echo '学算法';
}
public function relax()
{
echo '适当放松,保持健康心理';
}
public function sport()
{
echo '多运动,爱护身体';
}
protected function love()//有细节,由于love()是protected,子类可以是public,也可以是protected,毕竟有些爱不能说出
{
echo '恋爱,该谈就谈!';
}
}
?>2. 参数问题,如果抽象父类抽象方法有参数,子类继承的方法就必须存在这些参数,禁止额外参数:
<?php
/* 1. 准备一个抽象类 */
abstract class People
{
/* 抽象方法是服务于子类的,禁止private! */
abstract protected function love($who);//比如这里的love(),只能和一个人谈吧,所以指定一个参数 $who
}
/* 2.准备一个Programmar类 */
class Programmar extends People
{
/* 必须全部重写父类抽象方法 */
protected function love($who,$other)//有细节,明明抽象父类抽象方法love()只有一个参数,你这里有额外参数,那岂不是破坏约定,会报错!
{
echo '恋爱,该谈就谈!';
}
}
?>3. 重写完父类抽象方法后,子类可以自由添加自己的方法:
<?php
/* 1. 准备一个抽象类 */
abstract class People
{
/* 抽象方法是服务于子类的,禁止private! */
abstract public function study();//学习
}
/* 2.准备一个Programmar类 */
class Programmar extends People
{
/* 必须全部重写父类抽象方法 */
public function study()//由于抽象类的study()是public,所以子类就不能是protected!
{
echo '学算法';
}
/* 重写玩父类的抽象方法后,子类允许存在自己的方法 */
public function art()
{
echo '琴棋书画,样样精通!';
}
public function dream($aim)
{
echo '我要实现'.$aim;
}
}
?>总结:抽象类必须要用abstract关键字修饰,一个类只要有一个抽象方法就被视为抽象类;抽象方法通过abstract关键字修饰,没有“{}”具体方法,通过“;”结束抽象方法;继承抽象父类,子类必须全部实现父类抽象方法,同时保持参数的一致性。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程