PHP中的self :: $ bar和static :: $ bar有什么区别?


125

在下面的示例中,使用self和之间有什么区别static

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

产生

1234
1234

2
@deceze:这是一个类似的问题,但这不是重复的。这个问题询问将关键字与属性一起使用,而询问有关将其与构造函数一起使用。
BoltClock

Answers:


191

当您self用来指代一个类成员时,您指的是您在其中使用关键字的类。在这种情况下,您的Foo类定义了一个称为的受保护静态属性$bar。当您selfFoo类中使用来引用属性时,您是在引用同一类。

因此,如果您尝试self::$barFoo类中的其他地方使用,但您拥有一个Bar属性值不同的类,则它将使用Foo::$bar代替Bar::$bar,这可能不是您想要的:

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

当通过调用方法时static,您正在调用一个称为后期静态绑定的功能(在PHP 5.3中引入)。

在上述情况下,使用self将导致Foo::$bar(1234)。使用static会导致Bar::$bar(4321),因为使用时static,解释器会考虑Bar运行时在类内的重新声明。

您通常对方法甚至类本身使用后期静态绑定,而不是属性,因为您通常不会在子类中重新声明属性。static在以下相关问题中可以找到使用关键字调用后期绑定构造函数的示例:New self vs. new static

但是,这也不排除static与属性一起使用。


您可能很容易在子类中重新声明,父类可能是子类使用的默认值,除非它们重新声明。如果您在父类中,我想使用self ::是安全的,如果在子类中,您可以提出一个使用其中一个的参数,但是self ::如果您不希望使用它,也可以使用重新声明。
安德鲁

3
转到phpfiddle.org并运行它<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
Yevgeniy Afanasyev

2
前两段的措词令人困惑,具有不明确的代词“ it”,并且也很多余,因为后面的几段更清楚地解释了相同的信息。我建议将前两段替换为以“在上述情况下”开头的第二段。这样一来,最简单的答案就是底线。这很容易理解。
ahnbizcad '19

另一种思考方式:self::$abc在内部使用时class Foo与表示相同Foo::$abc$abc子类中的任何重新声明都不会影响它。AFAIK唯一的使用理由self是为了避免使用类名Foo,它可能更长。[这也意味着您可以在不更改所有这些位置的情况下更改类名-但这不是IMHO的原因。](PHP的名称选择很不幸,而且似乎倒退;“ static”是可以更改的名称-与自然语言单词“静态”的口语含义相反。)
ToolmakerSteve

4

如前所述,主要区别之一是static允许后期静态绑定。我发现的最有用的方案之一是为Singleton类创建基类:

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

return static::$name在Base类中使用时,将返回扩展时静态附加的内容。如果你使用return self::$name,然后B::getName()将返回一个空字符串因为这是在基类中声明。


0

随着self电话:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return self::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "123"
echo (new Bar)->getVar();

您可以在上面看到,即使我们$var用我们的Bar类重写了,它仍然返回123,因为我们已经明确地向PHP请求了self变量,而PHP 反过来又请求了Foos变量。

现在,如果我们将呼叫与交换static,我们将获得Bars的覆盖值:

随着static电话:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return static::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "234"
echo (new Bar)->getVar();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.