抽象类和接口都用于约束子类行为、支持多态,但抽象类强调“是什么”(类型归属与状态复用),接口强调“能做什么”(能力契约与解耦组合);抽象类可含属性和实现,仅单继承;接口仅方法声明(php 8.0+ 支持静态方法和常量),支持多实现。

PHP 中抽象类和接口都用于约束子类行为、支持多态,但设计目的和使用方式差异明显。面试时重点不是背定义,而是说清“为什么这么设计”以及“什么场景该选哪个”。
语法与基本规则不同
抽象类用 abstract class 声明,接口用 interface 声明;一个类只能 extends 一个抽象类,却可以 implements 多个接口。
- 抽象类可含普通方法(带实现)、抽象方法(无实现)、构造方法、protected/private 成员,甚至属性
- 接口只允许 public 抽象方法(PHP 8.0+ 支持静态方法和常量,但依然不能有属性或构造函数)
- 接口中所有方法默认 public,不能加访问修饰符;抽象方法不能是 private,至少是 protected
- 抽象类中若有抽象方法,该类必须声明为 abstract;但 abstract 类可以没有抽象方法(仅作基类用途)
核心关注点不一样
抽象类回答的是“它是什么”,强调类型归属与共性复用;接口回答的是“它能做什么”,强调能力契约与行为规范。
- 比如
Animal抽象类可定义$name属性、breath()公共实现、makeSound()抽象方法——体现生物共性 - 而
Swimmable、Flyable接口分别约定swim()和fly()行为——鸭子可以同时实现二者,飞机却只能实现后者 - 当新增功能时:往抽象类加一个普通方法,所有子类自动获得;往接口加一个新方法,所有实现类必须补实现,否则报错
典型使用场景对比
选抽象类,通常因为“有共同状态 + 部分逻辑可复用”;选接口,是因为“需要灵活组合多种能力,或对接第三方系统需解耦”。
立即学习“PHP免费学习笔记(深入)”;
- 适合抽象类:数据库模型基类(统一的
save()、validate()实现 + 抽象的getTable())、控制器基类(统一鉴权、日志、响应格式) - 适合接口:支付网关(
Payable)、缓存操作(Cacheable)、序列化协议(Serializable)——便于替换微信支付/支付宝,或 Redis/Memcached 实现 - 混合使用很常见:比如
class OrderController extends BaseController implements Payable, Loggable
继承与实现的约束细节
子类实现抽象方法时,签名必须兼容;接口方法实现则要求严格一致(PHP 7.2+ 启用严格模式后更明显)。
- 抽象方法参数数量必须匹配,但子类可增加带默认值的参数(如父类
getInfo($id),子类可写getInfo($id, $withDetail = false)) - 访问控制只能更宽松:父类
protected abstract function run();,子类必须用protected或public实现,不能private - 接口方法在实现类中必须是
public,哪怕接口声明时不写——这是强制的,不写等同于 public









