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

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

class Foo
{
protected static $bar = 1234;


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


}


Foo::instance();

生产

1234
1234
89753 次浏览

当您使用 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使用 打电话方法时,将调用一个称为 延迟静态绑定延迟静态绑定的特性(在 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关键字调用后期绑定构造函数的示例: 新的自我与新的静态

但是,这并不排除将 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

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

通过 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类覆盖了 $numbergetNumber()仍然返回 123

这是因为我们已经要求 PHP 给我们定义它的变量——它将返回 Phones 变量。

如果我们将 self调用与 static交换,我们将得到 Fax重写的值:

通过 static呼叫:

class Phone
{
protected static $number = 123;
    

public function getNumber()
{
// return self::$number;


return static::$number;
}
}
class Fax extends Phone
{
protected static $number = 234;
}


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

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

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)

我有一个很小的例子来说明 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 A::getSelfName(); // ClassA
echo A::getStaticName(); // ClassA


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