templateMethod()必须声明为final,否则子类可重写导致流程失控;abstract方法须用abstract protected声明;钩子方法建议protected+空实现;参数签名必须严格一致。

templateMethod() 必须声明为 final,否则子类绕过它就不是模板方法了。
PHP8.2 中必须用 final public function templateMethod()
PHP8.2 不再容忍模糊的流程控制。如果父类的模板方法没加 final,子类可能无意中重写它,导致流程跳步或重复执行。这不是警告,是设计失效的起点。
-
final是硬性要求,不是可选修饰——它锁住调用顺序,确保loadData()→validateData()→saveData()这个链条不被破坏 - 抽象方法必须用
abstract protected function声明,不能是private或省略可见性(PHP8.2 会报ParseError) - 钩子方法(如
beforeSave())建议用protected function+ 空实现,避免子类被迫实现无关逻辑
子类只能重写 abstract 或 protected 方法,不能碰 templateMethod()
常见错误是子类里又写了一个同名的 process(),以为在“扩展”,实际已脱离模板控制。PHP8.2 下这种写法不会报错,但运行时行为不可预测——比如父类日志没打、前置校验被跳过。
- 正确做法:只实现
abstract方法(如fetchData()),或选择性覆盖protected钩子(如logStep()) - 错误信号:子类中出现
public function templateMethod()或任何对父类模板方法的重定义 - PHP8.2 的严格类型检查不会拦这个错误,得靠代码审查或静态分析工具(如 PHPStan level 6+)提前发现
abstract 方法参数要和子类签名完全一致,否则触发 TypeError
PHP8.2 启用了更严格的继承一致性检查。如果父类声明 abstract protected function loadData(string $source): array;,子类实现时少了个类型声明、或多加了个默认值,运行时直接抛 TypeError。
立即学习“PHP免费学习笔记(深入)”;
- 所有
abstract方法的参数类型、返回类型、是否可为空(?stringvsstring),必须和子类一模一样 - 钩子方法如果带参数(如
protected function afterLoad(array $data): void),子类重写时也不能改动签名 - 建议统一开启
declare(strict_types=1);,避免弱类型掩盖签名差异
最容易被忽略的是钩子方法的调用时机——它藏在 final 方法体内,但执行结果会影响整个流程走向。比如 shouldSkipValidation(): bool 返回 true,后面整段校验就没了,而这个判断逻辑在子类里,父类根本看不到。



















