PHP 抽象类怎么用
很多刚接触PHP的开发者,都会把“抽象类”和“普通类”“接口”弄混——毕竟名字里带“抽象”俩字,听起来就像很高深的技术名词,其实它的用法特别生活化,只要举个常见的例子就能懂。
先搞懂:抽象类到底是啥?
咱们平时做项目,会不会遇到这种情况:比如要做一个“外卖平台”,里面有“商家”“骑手”“用户”三类角色,这三类都有“姓名”“手机号”“登录”的基础功能,但各自的“下单”“接单”“评价”功能又完全不一样——总不能每个角色都写一套重复的基础代码吧?

抽象类就是专门用来干这个的:它是一种“半成品类模板”,既可以写所有子类都能用的通用代码,还能规定子类必须实现的特殊代码,相当于给子类立了个“规矩”:基础功能你不用自己写,直接用我的,但你自己的特殊功能必须按我定的要求来做,不能偷懒。
这里要注意一个简单的区分:抽象类是“半成品”,你不能直接用它来实例化对象——就像你不能直接用“外卖角色模板”去当一个真实的商家,得按模板做出来具体的商家、骑手才行。
第一步:先写抽象类的“通用规则”
咱们就用刚才的外卖角色来举例子,先写一个最基础的角色抽象类:
`php
// 用abstract关键字声明这是抽象类
abstract class Role {
// 通用属性:所有角色都有姓名和手机号
protected $name;
protected $phone;
// 通用方法:所有角色都有登录功能,代码直接写在抽象类里
public function login($password) {
echo "{$this->name} 用密码 {$password} 成功登录平台!";
}
// 抽象方法:只写方法名,不写具体实现,必须加abstract关键字
// 意思是:所有子类必须实现这个方法,具体怎么干子类自己定
abstract public function doJob();
}
`
你看,这个抽象类里,login是所有人都能用的,直接写好;doJob是每个人的工作不一样,就只定个规矩——“你得有个工作方法,具体怎么干你自己来”。
第二步:子类继承抽象类,必须遵守“规矩”
抽象类写完了,接下来要做具体的角色,比如商家和骑手,这两个类要继承刚才的Role抽象类,而且必须实现抽象类里的doJob方法,不然直接报错。
比如写商家类:
`php
// 用extends关键字继承抽象类Role
class Merchant extends Role {
// 子类可以自己加专属属性,比如店铺名称
private $shopName;
// 子类的构造方法,初始化属性
public function __construct($name, $phone, $shopName) {
// 用parent调用抽象类里的通用属性赋值,不用自己再写一遍
$this->name = $name;
$this->phone = $phone;
$this->shopName = $shopName;
}
// 必须实现抽象类的doJob方法,不然会报错
public function doJob() {
echo "商家 {$this->shopName} 正在接单、安排配送!";
}
}
`
再写骑手类:
`php
class Rider extends Role {
private $vehicle; // 骑手的交通工具
public function __construct($name, $phone, $vehicle) {
$this->name = $name;
$this->phone = $phone;
$this->vehicle = $vehicle;
}
// 同样必须实现doJob方法,具体内容自己定
public function doJob() {
echo "骑手 {$this->name} 骑 {$this->vehicle} 正在送外卖!";
}
}
`
第三步:实际用起来,就这么简单
现在要创建对象,不能直接实例化抽象类,得实例化子类:
`php
// 实例化商家
$myShop = new Merchant("张老板", "138XXXX1234", "张记家常菜");
// 用抽象类里的通用方法,不用自己写
$myShop->login("123456"); // 输出:张老板 用密码 123456 成功登录平台!
// 调用子类自己的doJob方法
$myShop->doJob(); // 输出:商家 张记家常菜 正在接单、安排配送!
echo "<br>";
// 实例化骑手
$myRider = new Rider("李师傅", "135XXXX6789", "电动车");
$myRider->login("654321"); // 输出:李师傅 用密码 654321 成功登录平台!
$myRider->doJob(); // 输出:骑手 李师傅 骑 电动车 正在送外卖!
`
用抽象类的好处是什么?
其实就是两个核心:避免重复代码和规范子类行为。比如刚才的login方法,要是不用抽象类,每个角色都写一遍,改的时候要改N次,容易出错;用了抽象类,改一次所有子类都生效。另外,要是忘了写doJob方法,PHP会直接报错,不会出现“商家不会接单、骑手不会送单”的bug,保证了代码的规范性。
最后再补个小提醒:抽象类里可以写普通方法、属性,也可以写多个抽象方法,但抽象方法只能在抽象类里,普通类不能有抽象方法——就像半成品模板只能是“半成品”,你要是做了个成品类,就不能留“没写具体内容的工作方法”了。