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 【问题描述】:在下面的示例中使用self
和static
有什么区别?
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
交换,我们将获得Fax
s 覆盖值:
与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】:我有一个小例子显示self
和static
之间的区别。使用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 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
PHP 中的 PHP_SELF、SCRIPT_NAME 和 REQUEST_URI 有啥区别? [复制]