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

Posted

技术标签:

【中文标题】PHP 中的 self::$bar 和 static::$bar 有啥区别?【英文标题】:What is the difference between self::$bar and static::$bar in PHP?PHP 中的 self::$bar 和 static::$bar 有什么区别? 【发布时间】:2012-07-27 10:45:13 【问题描述】:

在下面的示例中使用selfstatic 有什么区别?

class Foo

    protected static $bar = 1234;

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



Foo::instance();

产生

1234
1234

【问题讨论】:

@deceze:这是一个类似的问题,但不是重复的。这一个询问如何将关键字与属性一起使用,而该关键字询问如何将它们与构造函数一起使用。 【参考方案1】:

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

因此,如果您尝试在 Foo 类的其他位置使用 self::$bar,但您有一个具有不同属性值的 Bar 类,它将使用 Foo::$bar 而不是 Bar::$bar,这可能不会做你想做的:

class Foo

    protected static $bar = 1234;


class Bar extends Foo

    protected static $bar = 4321;

当您通过static调用一个方法时,您正在调用一个名为late static bindings 的功能(在php 5.3 中引入)。

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

// self
var_dump(Foo::$bar);
// (int) 1234

// static
var_dump(Bar::$bar);
// (int) 4321

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

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

【讨论】:

您可能很容易在子类中重新声明,父类可能是子类使用的默认值,除非他们重新声明。如果您在父类中,我想使用 self:: 是安全的,如果在子类中,您可以提出使用任何一个的参数,但是如果您不希望使用 self:: 也可以重新声明。 转到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(); ?> 前两段的措辞令人困惑,有一个模棱两可的代词“它”,而且也是多余的,因为后面的段落更清楚地解释了相同的信息。我建议将前两段替换为后面以“在上述场景中”开头的段落。这样,底线,切入正题的答案就在顶部。它清晰易懂。 另一种思考方式:self::$abc,在class Foo 中使用时与Foo::$abc 相同。它不会受到子类中$abc 的任何重新声明的影响。 AFAIK,使用self 的唯一原因是作为速记,以避免使用可能更长的类名Foo。 [这也意味着您可以在不更改所有这些位置的情况下更改类名-但这并不是恕我直言的原因。](PHP 的名称选择很不幸,而且似乎倒退;“静态”是可以更改的名称-与自然语言单词“static”的口语含义相反。)【参考方案2】:

self 通话:

class Phone

    protected static $number = 123;
    
    public function getNumber()
    
        return self::$number;
    

class Fax extends Phone

    protected static $number = 234;


// Displays: "123"
echo (new Fax)->getNumber();

您可以在上面看到,即使我们用 Fax 类覆盖了 $number,它仍然返回 123,因为我们已经明确要求 PHP 提供 self 变量,而后者又要求 @改为 987654328@s 变量。

现在,如果我们将self 调用与static 交换,我们将获得Faxs 覆盖值:

static 通话:

class Phone

    protected static $number = 123;
    
    public function getNumber()
    
        return static::$number;
    

class Fax extends Phone

    protected static $number = 234;


// Displays: "234"
echo (new Fax)->getVar();

【讨论】:

【参考方案3】:

我有一个小例子显示selfstatic 之间的区别。使用static:: 执行后期静态绑定,从而绑定子类中的变量值。

class A  // Base Class
    protected static $name = 'ClassA';
    public static function getSelfName() 
        return self::$name;
    
    public static function getStaticName() 
        return static::$name;
    


class B extends A 
    protected static $name = 'ClassB';


echo B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB

【讨论】:

【参考方案4】:

也许这个自我解释的代码可以帮助你:

class Foo 

    protected static $bar = 'parent value';

    public static function test() 
    
        var_dump('I am your father');
        var_dump('self:: here means '.self::$bar);
        var_dump('static:: here means '.static::$bar);
    


class Bar extends Foo 

    protected static $bar = 'child value';

    public static function test() 
    
        parent::Test();

        var_dump('I am the child');
        var_dump('self:: here means '.self::$bar);
        var_dump('static:: here means '.static::$bar);
    


Bar::test();
Foo::test();

这会产生以下输出(为了清楚起见,我添加了换行符):

'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means child value' (length=31)

'I am the child' (length=14)
'self:: here means child value' (length=29)
'static:: here means child value' (length=31)

'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means parent value' (length=32)

【讨论】:

【参考方案5】:

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

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 将返回扩展时静态附加的内容。如果您要使用return self::$name,那么B::getName() 将返回一个空字符串,因为这是在 Base 类中声明的内容。

【讨论】:

以上是关于PHP 中的 self::$bar 和 static::$bar 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

类的索引成员作为python中的列表

面向对象-01

javascript中的静态自我成员[重复]

PHP 中的 PHP_SELF、SCRIPT_NAME 和 REQUEST_URI 有啥区别? [复制]

Apache 2.4.26 中的 SCRIPT_FILENAME 和 PHP_SELF 错误

今天写测试代码时遇到的小坑