PHP抽象类必须用abstract关键字声明,仅含抽象方法的非abstract类会报错;抽象类可含普通成员,不可实例化;抽象方法无方法体、需显式访问控制符、不能为private或static(8.2前);子类须实现全部抽象方法,签名须严格兼容;抽象类表“is-a”关系,接口表“can-do”关系。

PHP 抽象类必须用 abstract 关键字声明
不加 abstract 修饰的类,哪怕里面全是抽象方法,也不是抽象类——PHP 会直接报错 Parse error: Cannot inherit from abstract class 或更隐蔽的运行时错误。抽象类不是靠“有没有抽象方法”来判断的,而是靠声明本身。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 类定义开头必须写
abstract class MyClass,缺一不可 - 抽象类可以包含普通方法、属性、构造函数,也能被
final修饰(但意义不大) - 子类继承时,必须用
extends,且需实现所有abstract方法,否则子类也得声明为abstract - 不能用
new实例化抽象类:new AbstractClass()会触发Fatal error: Cannot instantiate abstract class
抽象方法只能出现在 abstract 类里,且不能有方法体
抽象方法是“契约”,只规定签名,不提供实现。它不是可选功能,而是强制子类响应的接口。常见错误是给抽象方法写了花括号和内容,比如 abstract function foo() { return 1; } —— 这会导致解析失败,报 Parse error: Abstract function ... cannot contain body。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 抽象方法必须用
abstract修饰,且以分号结尾:abstract public function getName(): string; - 访问控制符(
public/protected)必须显式写出,private abstract不合法 - PHP 8+ 支持返回类型和参数类型,但子类重写时不能缩小类型范围(如父类返回
string,子类不能只返回"hello"字面量类型) - 抽象方法不能是
static(PHP 8.2 之前),8.2+ 允许abstract static,但调用逻辑完全不同,慎用
继承抽象类时,方法签名必须严格匹配,否则报 Declaration must be compatible
这不是警告,是致命错误。PHP 对抽象方法的实现要求非常严格:参数名可以不同,但数量、类型、默认值、可变参数(...)位置,以及返回类型都必须兼容。常见翻车点是加了可选参数、改了类型声明、或漏了 ?string 中的问号。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 子类方法参数不能比父类少(除非是可选参数),也不能多(即使带默认值也不行)
- 如果父类方法是
function save(array $data),子类写成function save($data)会报错——类型声明缺失即不兼容 - 返回类型协变从 PHP 7.4 开始支持,但仅限于对象类型;基础类型(
int,string)必须完全一致 - 用 IDE 的“go to declaration”核对签名比肉眼检查靠谱得多
抽象类 ≠ 接口,别用它替代 interface 做多继承
PHP 不支持多继承,一个类只能 extends 一个抽象类,但可以 implements 多个接口。有人试图把多个“能力”塞进一个抽象类,结果发现子类被锁死,没法再复用其他基类逻辑。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 抽象类适合表达“是什么”(is-a)关系:比如
abstract class Animal,子类是Dog、Cat - 接口适合表达“能做什么”(can-do)关系:比如
interface Flyable、interface Swimmable,可自由组合 - 抽象类里放公共实现代码(比如
logAction()),接口只管约定;混用时优先让抽象类implement接口,再由子类继承该抽象类 - 如果只是想约束方法名和签名,没共享逻辑,直接用
interface更轻量、更灵活
抽象类真正的复杂点不在语法,而在设计意图的拿捏:什么时候该抽一个抽象基类,什么时候该拆成接口+trait+具体类。多数人踩坑不是因为不会写 abstract,而是过早抽象,或者把本该是组合的地方硬做成继承。










