self
在下面的示例中使用和有什么区别static
?
class Foo
{
protected static $bar = 1234;
public static function instance()
{
echo self::$bar;
echo "\n";
echo static::$bar;
}
}
Foo::instance();
生产
1234
1234
当您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)。并且 usingstatic
将导致Bar::$bar
(4321) 因为 with ,解释器会在运行时static
考虑类内的重新声明。Bar
// self
var_dump(Foo::$bar);
// (int) 1234
// static
var_dump(Bar::$bar);
// (int) 4321
您通常对方法甚至类本身使用后期静态绑定,而不是属性,因为您不经常在子类中重新声明属性;static
可以在以下相关问题中找到使用关键字调用后期绑定构造函数的示例: New self vs. new static
但是,这也不排除使用static
with 属性。
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
有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();
你可以在上面看到,即使我们已经$number
用我们的Fax
类覆盖了 ,它仍然返回123
,因为我们已经明确地要求 PHP 提供self
变量,而 PHP 反过来又要求Phone
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();
如前所述,主要区别之一是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
thenB::getName()
将返回一个空字符串,因为这是在 Base 类中声明的内容。
也许这个自我解释的代码可以帮助你:
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)