抽象方法必须定义在abstract类中且无方法体,子类未实现会触发编译期致命错误;其签名与子类实现必须严格一致,访问控制符须为public或protected,不可private;判断抽象类依据是声明而非内容。

抽象方法必须写在 abstract 类里,且不能有方法体;子类不实现就会报致命错误——不是警告,是直接中断执行。
abstract 方法的语法要求
抽象方法不是“可选实现”,而是编译期强制契约。它只声明签名,不提供任何逻辑:
- 必须用
abstract关键字修饰,且只能出现在abstract class中 - 必须显式声明访问控制符(
public或protected),不能是private(8.2 之前也不允许static) - 不能带方法体:写
abstract function foo() { }或abstract function foo() { return 1; }都会触发Parse error: Abstract function cannot contain body - 参数列表、返回类型(PHP 7.0+)必须与子类实现严格一致;哪怕漏一个默认值(比如父类
function bar($x = null),子类写成function bar($x)),也会报Fatal error: Declaration of ... must be compatible with ...
子类不实现抽象方法会发生什么
不是运行时报错,而是在类加载/解析阶段就失败——只要你尝试实例化或反射该子类,PHP 就会立刻抛出致命错误:
- 如果子类没实现全部抽象方法,又没声明为
abstract,会触发Fatal error: Class ChildClass contains abstract method and must therefore be declared abstract or implement the remaining methods - 这个检查发生在字节码编译时,IDE 和静态分析工具(如 PHPStan)能提前捕获,但不会等到你调用
new ChildClass()才发现 - 注意:即使子类只漏实现一个抽象方法,整个类都无法被加载,更别说运行了
为什么不能靠“有没有抽象方法”来判断是否是抽象类
PHP 不看内容,只看声明。这是最容易踩的坑:
立即学习“PHP免费学习笔记(深入)”;
- 写一个普通类
class Foo { abstract function bar(); }—— 直接报Parse error: Cannot inherit from abstract class或更奇怪的解析失败,因为 PHP 要求含抽象方法的类必须显式加abstract - 反过来,一个
abstract class Bar里可以完全不写抽象方法,它依然是抽象类,依然不能被new实例化 - 所以判断依据永远是类定义开头有没有
abstract class,而不是它里面有没有abstract function
抽象方法和接口方法的区别在哪
关键差异不在“强制实现”,而在“上下文约束”:
- 抽象方法属于某个具体类层级,可复用父类的属性、构造函数、普通方法(比如
sleep()这种通用逻辑) - 接口方法全是
public,且不能带任何实现;抽象方法可以是protected,也能配合final方法锁定部分行为 - 一个类只能
extends一个抽象类,但可以implements多个接口;若想同时继承结构 + 强制契约,常见做法是让抽象类implements接口(例如abstract class Tag implements Serializable) - 抽象方法签名兼容性检查比接口更严格:接口允许子类扩大访问权限(如接口声明
public,实现类用public或更宽松的?其实没有更宽松的,但抽象类中protected抽象方法,子类必须用protected或public,不能降级为private)
真正难的不是写对语法,而是设计时想清楚:这个方法到底该放进抽象类做契约,还是拆进接口表达能力?一旦选错,重构成本远高于改几行 abstract。



















