老K博客 - 一个源码和技术分享的博客

掌握 PHP 静态成员:self::, parent::, static:: 详解

老K博客
2025-01-07 / 0 评论 / 10 阅读 / 正在检测是否收录...
广告

m5migl86.png

前言

在 PHP 中,静态成员(包括方法和属性)直接隶属于类,而非类的实例对象。这意味着我们无需实例化对象,就能直接访问类的静态成员。这一特性在需要跨对象共享数据或功能时尤为有用。

PHP 提供了 self::parent::static:: 三个关键字来访问静态成员,它们各自拥有不同的工作机制,尤其是在继承关系中。本文将深入解析这三个关键字的运作原理,并结合实例阐明它们之间的区别。

何时使用静态成员

  • 模拟全局变量: 将静态属性视为类内部的全局变量,所有实例都能共享访问。
  • 提供工具方法: 静态方法适用于提供独立于具体对象实例的实用功能。
  • 定义类常量: 使用静态属性定义类级别常量,确保其值在整个应用生命周期内保持不变。
  • 实现单例模式: 静态方法和属性是实现单例模式(确保一个类只有一个实例)的关键要素。

    调用静态方法

    要调用静态方法,请使用 :: 运算符,后跟方法名称。

以下是示例:

class MyClass {
    public static function greet() {
        echo "Hello, world!";
    }
}

MyClass::greet(); // 输出: Hello, world!

调用静态属性

要访问静态属性,也可以使用 :: 运算符,后跟属性名称。

以下是示例:

class MyClass {
    public static $count = 0;

    public static function incrementCount() {
        self::$count++;
    }
}

MyClass::incrementCount();
echo MyClass::$count; // 输出: 1
Use code with caution.

三个关键词:self::、、parent::和static

1. self::

self:: 关键字始终指向 代码编写的类 本身,不考虑任何继承关系。这意味着即使子类重写了父类的静态方法或属性, self:: 仍然会引用父类中定义的版本。

2. parent::

parent:: 关键字用于从 直接父类 中调用静态方法或属性。它会绕过子类中任何重写的方法或属性,确保使用的是 父类 的版本。

3. static::

static:: 关键字与 self:: 类似,但它引入了 后期静态绑定 机制。这意味着 static:: 会根据运行时环境动态地绑定到最 派生类 中的静态方法或属性,即使调用代码位于父类中。

举例说明差异
让我们看看这些关键字在具有继承的 PHP 程序中是如何表现的。

示例 1:使用self
class A {
    public static function sayHello() {
        return "Hello from A";
    }

    public static function test() {
        return self::sayHello();
    }
}

class B extends A {
    public static function sayHello() {
        return "Hello from B";
    }
}

echo B::test(); // 输出: "Hello from A"

在这个例子中, self::sayHello() 语句出现在类 A 的代码中,因此 self:: 指向的是类 A 本身。 尽管类 B 重写了 sayHello() 方法,但由于 self:: 的绑定机制,程序仍然会调用 父类 A 中的 sayHello() 方法,最终输出 "Hello from A"。

示例 2:使用parent
class A {
    public static function sayHello() {
        return "Hello from A";
    }
}

class B extends A {
    public static function sayHello() {
        return parent::sayHello() . " and B";
    }
}

echo B::sayHello(); // 输出: "Hello from A and B"

在这个例子中,类 B 中的 parent::sayHello() 语句明确指示调用 父类 A 的 sayHello() 方法。因此,程序会先输出父类 A 中的消息,然后拼接上类 B 自身的消息,最终输出 "来自 A 和 B 的问候"。

示例 3:使用static
class A {
    public static function sayHello() {
        return "Hello from A";
    }

    public static function test() {
        return static::sayHello();
    }
}

class B extends A {
    public static function sayHello() {
        return "Hello from B";
    }
}

echo B::test(); // 输出: "Hello from B"

这段代码中, static::sayHello() 语句位于类 A 中,但由于 static:: 支持后期静态绑定,它会指向 运行时确定的最底层派生类,也就是类 B。最终,程序调用的是类 B 中的 sayHello() 方法,输出 "Hello from B"。

主要区别

  • self::: 引用当前代码所在的类,不考虑继承关系。 当我们希望子类重写方法时,父类中的调用不受影响,就可以使用 self::
  • parent::: 专门用于调用父类中的方法或属性,即使子类进行了重写。 当我们需要在子类中扩展父类的功能,但仍然希望保留对父类原始方法的访问权限时,就可以使用 parent::
  • static::: 实现后期静态绑定,根据运行时环境动态绑定到最派生类的方法或属性。 当我们希望方法的行为能够根据调用它的类动态调整时,就可以使用 static::

深入理解 self::parent::static:: 之间的区别,有助于我们编写更加健壮、易于维护的面向对象 PHP 代码,尤其是在处理复杂的继承关系时。

本文共 964 个字数,平均阅读时长 ≈ 3分钟
广告
0

海报

正在生成.....

评论 (0)

语录
取消
CC BY-NC-ND