引言:为什么这个问题困扰着每个 PHP 开发者?
\n\n如果你曾经用面向对象风格编写过 PHP 代码,你肯定遇到过这个难题:何时使用 self,何时使用 $this? 这个问题是 Stack Overflow 上最热门的问题之一(数千次浏览和数十个投票)。看起来区别很明显,但一旦深入挖掘,即使是经验丰富的开发者也会开始混淆。
在本文中,我们将把一切梳理清楚。你将了解到:
\n- \n
self和$this的根本区别是什么; \n - 在哪些情况下它们各自是必需的; \n
- 继承和静态上下文是如何工作的; \n
- 当然,还会看到可以立即应用的现实代码示例。 \n
让我们一劳永逸地搞清楚吧!
\n\n基本规则:静态 vs 实例
\n\n最重要的一点需要记住:
\n- \n
$this— 引用当前对象(类的实例)。仅在非静态上下文中工作。 \n self— 引用编写代码的当前类。用于访问静态属性、常量和静态方法。 \n
听起来很简单?让我们通过一个示例来验证。
\n\n示例 1:简单的类
\n<?php\nclass Coffee\n{\n public static $type = '阿拉比卡';\n public $sugar = 2;\n\n public function info()\n {\n // $this — 用于对象属性\n echo "糖:{$this->sugar} 勺。";\n\n // self — 用于静态属性\n echo "咖啡类型:" . self::$type;\n }\n}\n\n$cup = new Coffee();\n$cup->info(); // 输出:糖:2 勺。咖啡类型:阿拉比卡\n?>\n\n这里一切都很合理:$this->sugar 对每杯咖啡都是唯一的,而 self::$type 对所有咖啡都是通用的。
继承的陷阱:self vs static
\n\n这里开始变得有趣了。许多人认为 self 具有多态性,但事实并非如此。self 始终指向它被编写所在的类,即使你从子类调用方法。
如果你需要代码考虑到调用它的类(后期静态绑定),请使用 static。
示例 2:继承与陷阱
\n<?php\nclass Animal\n{\n public static $sound = '...';\n\n public static function speak()\n {\n // 注意:self 是 Animal,而不是 Dog!\n echo self::$sound;\n }\n\n public static function speakCorrect()\n {\n // static 是调用该方法的类\n echo static::$sound;\n }\n}\n\nclass Dog extends Animal\n{\n public static $sound = '汪汪!';\n}\n\nDog::speak(); // 输出:...(因为 self = Animal)\nDog::speakCorrect(); // 输出:汪汪!(因为 static = Dog)\n?>\n\n这个示例是 bug 的常见原因。如果你在编写库并期望子类能够重写静态属性,请始终使用 static 而不是 self。
什么时候必须使用 self?
\n\n有些情况下 $this 根本不起作用,self 是唯一的选择:
- \n
- 静态方法:在声明为
public static function的方法内部,没有对象,因此$this不可用。只能使用self。 \n - 类常量:通过
self::CONSTANT(或ClassName::CONSTANT)访问。 \n - 静态属性:
self::$property。 \n - 在构造函数或析构函数内部:虽然那里可以使用
$this,但对于静态操作,最好使用self。 \n