延迟静态绑定控制在继承中静态上下文中引用的是哪个类。关键区别:self:: 指的是代码被编写的类,而**static::** 指的是运行时实际被调用的类——当子类继承父类的静态方法时这很重要。
问题:self:: 是"早期绑定"
{
{
();
}
{
();
}
}
{}
(::());
(::());
self:: 在定义时被解析(总是定义的类),所以即使通过 ChildClass 调用,new self() 也会创建 ParentClass。static:: 在运行时被解析为实际调用的类——所以 new static() 能正确地创建 ChildClass。
class Model {
public static function make(): static { // static return type + new static()
return new static(); // ✅ returns an instance of whatever subclass called it
}
}
class User extends Model {}
class Post extends Model {}
User::make(); // returns a User (not a Model) — thanks to late static binding
Post::make(); // returns a Post
延迟静态绑定使得继承的工厂方法、流式生成器和 ORM 模式能返回正确的子类实例——这对依赖静态方法 API 的框架至关重要。
self:: → the class where the code is WRITTEN (early/static binding)
static:: → the class CALLED at runtime (late static binding) — for subclass-aware code
parent:: → the parent class (for calling overridden parent methods)
延迟静态绑定(static:: 对比 self::)是一个重要但经常被误解的 PHP 概念,特别与理解框架如何实现基于继承的静态 API 相关。
关键区别——self:: 绑定到代码被编写的类而**static:: 绑定到运行时实际被调用的类**——在子类继承父类的创建实例或引用类的静态方法时很重要:使用 self::,继承的工厂方法总是返回父类型(一个 bug),而**static:: 能正确地返回调用的子类**。
这正是使得继承的工厂方法、流式生成器和 ORM 模式能够工作的原因,而这些正是 Laravel 的 Eloquent 等框架所依赖的(例如 User::make() 返回 User,而不是基类 Model)。
理解延迟静态绑定对于正确使用这些框架模式以及编写自己的继承感知的静态方法都很重要,这些方法应该与子类正确配合。
虽然这是一个较高级的主题,但它是引发微妙 bug 和困惑的常见来源("为什么这返回的是父类?"),理解 self::/static::/parent:: 的区别反映了对 PHP 对象模型和继承行为的更深入理解——对于使用和构建现代 PHP 框架中常见的基于静态方法、继承密集的 API 很有价值。
一个包含详细解答的 IT 面试题库——从初级到高级。
捐赠