PHP多级继承最佳实践:BC类抛异常强制重写是否合理?
问题:子类强制重写方法的实现是否符合最佳实践?
在架构开发过程中,我产生了一个疑问:当前的实现是否符合最佳实践?
现有抽象类A:
abstract class A { protected mixed $object; public function __construct() { $this->loadObject() ->fuc1(); } abstract protected function loadObject(): self; abstract public function fuc1(): bool; abstract public function fuc3(): iterable; }
由于类B和C存在相同方法,我为它们创建了基类BC,代码如下:
class BC extends A { protected string $x; protected string $y; protected function loadObject(): self { throw new \Exception('Child must implement loadObject'); } public function fuc1(): bool { //Some Codes } public function fuc3(): iterable { //Some Codes } }
类B和类C的实现如下:
class B extends BC { protected function loadObject(): self { $this->object = new SomeObject(); return $this; } } class C extends BC { protected function loadObject(): self { $this->object = new SomeObject2(); return $this; } }
同时,无法将loadObject方法移至BC类,因为可能有类D直接继承A;若依赖接口实现,又担心开发者忘记让B/C实现接口导致A类出现问题。请问这种通过在BC类中抛出异常强制子类重写loadObject方法的方式是否为良好实践?
回答
这种通过运行时抛异常强制子类重写方法的方式不是良好实践,核心问题在于:错误只会在代码运行时暴露,无法在编写或静态检查阶段提前发现,很容易导致开发者遗漏实现,等到线上或测试时才触发报错,排查成本高。
更规范的解决方案是把BC也声明为抽象类,让loadObject继续保持抽象方法:
abstract class BC extends A { protected string $x; protected string $y; // 保持抽象方法,强制子类必须实现 abstract protected function loadObject(): self; public function fuc1(): bool { // Some Codes } public function fuc3(): iterable { // Some Codes } }
这个方案的优势:
- 约束前置:任何继承BC的子类(比如B、C)如果不实现
loadObject,在代码编写阶段(或IDE静态检查时)就会直接报错,从根源上避免遗漏实现的问题。 - 不影响原有场景:类D依然可以直接继承抽象类A,不受BC的影响,完全符合需求。
- 符合面向对象设计原则:抽象类的核心作用之一就是定义子类必须遵守的契约,这种方式比运行时抛异常更贴合抽象类的设计初衷。
内容的提问来源于stack exchange,提问作者sajjad rezaei
相关产品推荐
相关产品推荐

