New self vs. new static:2025年灵活PHP代码的秘密

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:一个改变一切的小字母

\n\n

想象一下:您正在编写一个很棒的PHP框架,或者只是为自己项目写一个库。一切运行完美,但一个月后,您发现子类的行为与预期不符。您创建了一个对象,但它——啪!——返回了父类的实例。熟悉吗?欢迎加入那些遇到new self vs. new static问题的俱乐部。

\n\n

这个问题在Stack Overflow上获得了数千次浏览,这并非没有原因。PHP中self和static之间的区别不仅仅是语法糖,而是一个基础机制,它既可以拯救您的项目,也可以将其变成维护的噩梦。在2025年,当PHP继续演进时,理解后期静态绑定(Late Static Binding)已成为任何有自尊心的开发者的必备技能。

\n\n

在本文中,我们不仅仅是复述文档。我们将分析真实案例,展示反模式,并给出清晰的最佳实践,您可以立即应用。开始吧!

\n\n

主体部分:self vs. static——上下文的较量

\n\n

1. self——编译器的保守派

\n\n

PHP中的关键字self始终引用它被写入的类。把它想象成一个永远不会改变的老朋友。当您在父类中编写new self()时,这段代码将始终创建该父类的对象——即使它被子类调用。

\n\n
<?php\nclass Animal {\n    public static function create() {\n        return new self(); // 始终是 Animal\n    }\n}\n\nclass Dog extends Animal {\n    // 继承 create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // 输出:Animal\n?>
\n\n

看到了吗?我们调用了Dog类的方法,却得到了Animal。这对新手来说常常是个意外。问题出在哪里?在于self是在编译阶段解析的。PHP“封存”了对声明该方法的类的引用,任何继承的魔法都无法改变这一点。

\n\n

2. static——后期绑定的革命者

\n\n

而static则完全相反。它在方法调用时工作,并确定是哪个类调用了它。这就是后期静态绑定(Late Static Binding),自PHP 5.3.0引入。

\n\n
<?php\nclass Animal {\n    public static function create() {\n        return new static(); // 创建调用该方法的类的实例\n    }\n}\n\nclass Dog extends Animal {\n    // 继承 create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // 输出:Dog\n?>
\n\n

这是一个转折点!现在Dog::create()返回一只狗,而不是一个抽象的动物。static查看是谁调用了该方法,并创建该类的对象。这在构建类层次结构时提供了难以置信的灵活性。

\n\n

3. 何时使用self,何时使用static?

\n\n

黄金法则:当您需要硬绑定到当前类时使用self,当您希望子类能够重写行为时使用static。

\n\n

以下是一些具体场景:

\n\n

场景A:工厂方法(使用static)

\n

经典示例——工厂方法模式。您希望每个子类都能创建自身的实例。

\n\n
<?php\nabstract class Vehicle {\n    abstract public function getType(): string;\n\n    public static function create(): static {\n        return new static();\n    }\n}\n\nclass Car extends Vehicle {\n    public function getType(): string {\n        return '汽车';\n    }\n}\n\nclass Bike extends Vehicle {\n    public function getType(                

博客

书籍推荐