PHP中静态类方法中的self::和className::有什么区别?

23

我猜可能没有任何区别,只是个人喜好而已。但当我阅读各种PHP代码时,我遇到了两种访问类方法的方式。

那么有什么区别呢:

class Myclass
{
    public static $foo;

    public static function myMethod ()
    {
        // between:
        self::$foo;
        // and
        MyClass::$foo;
    }
}

抱歉,我第一次回答错误了。请查看更新后的答案。 - Artefacto
2个回答

43

(注:最初版本说没有区别。实际上是有的)

确实存在一些细微的差异。self:: 转发静态调用,而 className:: 不会。这只在 PHP 5.3+ 中的延迟静态绑定中才有所影响。

在静态调用中,PHP 5.3+ 会记住最初被调用的类。使用 className:: 会让 PHP “忘记”此值(即将其重置为 className),而 self:: 会保留它。请考虑以下情况:

<?php
class A {
    static function foo() {
        echo get_called_class();
    }
}
class B extends A {
    static function bar() {
        self::foo();
    }
    static function baz() {
        B::foo();
    }
}
class C extends B {}

C::bar(); //C
C::baz(); //B

1
重要更正/添加:static 关键字是为了此目的而引入的。在每个 A、B 和 C 中添加 const FOO = __CLASS__;,并使 A::foo() 打印出 self::FOOstatic::FOO 两者。只有后者对于 C::baz() 实际上才是正确的。 - janmoesen
1
@Artefacto,你会为一个不使用后期静态绑定的典型应用程序推荐哪个呢?你会选择self::还是MyClass::?你建议哪一个更高效?谢谢。 - Lea Hayes
7
这句话的大意是,“这主要是关于编码风格的问题,但在重构时,self::更方便使用。” - Artefacto
@Artefacto 感谢您澄清,我将继续使用 self::,因为这是我一直在使用的。我遇到了这个问题,并且很好奇是否会有有用的性能提升。 - Lea Hayes
1
为了澄清@janmoesen的评论:以下是错误的::“self::转发静态调用”。不,链接的文档显示self::不会转发静态调用。如果您想要转发(后期静态绑定),请使用static::。如果C也定义了static function foo() { echo "Truth"; },则会看到这一点。如果LSB发生,则C::bar将回显“Truth”。但它不会。(已测试)那么C::bar如何回显“C”?当C::bar即将执行时,C存储在某些内部php位置中:“后期静态绑定通过存储在最后一个“非转发调用”中命名的类来工作。” - ToolmakerSteve
1
因此,这个例子演示了LSB的前半部分 - 存储类名C。然而,self::foo在查找要执行的foo版本时没有使用该类名。static::foo将为函数版本执行正确的搜索。如果这个解释让你感到困惑,那么你可能没有代码需要考虑这些问题。使用self::是很方便的,直到你遇到它不能满足你的需求的情况。 - ToolmakerSteve

1

使用self关键字,你可以在类内部使用它,在"MyClass"中,你也可以在外部引用它:

$instance = new Myclass();
$variable = $instance::$foo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接