Answers:
当您self用来指代一个类成员时,您指的是您在其中使用关键字的类。在这种情况下,您的Foo类定义了一个称为的受保护静态属性$bar。当您self在Foo类中使用来引用属性时,您是在引用同一类。
因此,如果您尝试self::$bar在Foo类中的其他地方使用,但您拥有一个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与属性一起使用。
<?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,它可能更长。[这也意味着您可以在不更改所有这些位置的情况下更改类名-但这不是IMHO的原因。](PHP的名称选择很不幸,而且似乎倒退;“ static”是可以更改的名称-与自然语言单词“静态”的口语含义相反。)
如前所述,主要区别之一是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()将返回一个空字符串因为这是在基类中声明。
随着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();