PHP类继承用extends实现单继承,子类仅能继承一个父类;需注意final限制、构造函数需显式调用parent::__construct()、重写方法时用parent::调用父逻辑,trait优先级高于父类但低于子类,深层继承易引发维护与测试风险。
PHP类继承的基本写法和关键字
PHP用
关键字实现单继承,子类只能继承一个父类。语法很简单:
,但要注意:父类不能是
,子类不能用
修饰自身(除非你明确不希望被进一步继承)。
常见错误是把
写成
或
——PHP不认这些词,会直接报错
。
父类的
和
成员可在子类中直接访问;
成员不可见
构造函数不会自动继承,子类定义了
就必须显式调用
,否则父类初始化逻辑会被跳过
如果父类构造函数有必填参数,而子类没传,运行时会抛出
重写方法时如何调用父类同名方法
用
显式调用父类实现,这是避免逻辑丢失的关键操作。比如日志记录、权限校验等通用前置逻辑常放在父类方法里,子类在重写时得主动补上这一句。
容易踩的坑是只顾重写功能,忘了调用父逻辑,导致缓存未清理、连接未关闭或审计日志缺失。示例:
立即学习
“
PHP免费学习笔记(深入)
”;
trait 与继承混用时的优先级和冲突处理
PHP不支持多继承,但允许用
补充功能。当
、父类、子类都定义了同名方法时,优先级是:子类 > trait > 父类。
如果多个
提供同名方法,PHP会报致命错误
,必须用
明确排除其中一个,或用
重命名。
别指望
能绕过访问控制——
方法在
中声明后,在使用它的类里仍是私有的
中的
属性属于使用它的类,不是共享的;不同类引入同一
,各自拥有独立副本
想让子类强制实现某个行为?用抽象方法 +
组合比纯继承更灵活
继承链过深带来的维护风险
超过三层继承(A → B → C → D)就该警惕了。调试时
只返回直接父类,
才能拿到完整链,但实际开发中往往需要人工追溯。
性能上影响不大,但可读性和测试成本明显上升:改一个父类方法可能意外影响下游多个子类,而 IDE 很难准确推导所有调用路径。
用
或
判断类型时,继承链越长,判断结果越“宽泛”,容易掩盖具体语义
序列化对象时,深层继承可能导致
/
行为难以预测
真正需要复用逻辑的地方,优先考虑组合(
)而非继承(
),比如把通用校验抽成独立服务类,通过属性注入
继承不是语法糖,它是设计契约。父类接口一旦发布,所有子类都绑定在这个契约上——改一个
方法签名,可能让十几个子类集体报错。动手前先问一句:这个“是”关系真的成立吗?
extendsclass Child extends ParentfinalfinalextendsinheritinheritsParse error: syntax error, unexpected token "inherits"publicprotectedprivate__construct()parent::__construct()ArgumentCountErrorparent::methodName()class DatabaseService {
public function save($data) {
$this->log("Saving...");
// 实际保存逻辑
}
}
class UserRepo extends DatabaseService {
public function save($data) {
parent::save($data); // 必须加这行,否则 log 不会输出
$this->sendNotification($data);
}
}traittraittraitPHP Fatal error: Trait method X has not been appliedinsteadofastraitprivatetraittraitstatictraittraitget_parent_class()class_parents()is_a($obj, 'ClassName')$obj instanceof ClassName__sleep()__wakeup()has-ais-aprotected