159

self在下面的示例中使用和有什么区别static

class Foo
{
    protected static $bar = 1234;

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

}

Foo::instance();

生产

1234
1234
4

5 回答 5

224

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

因此,如果您尝试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

但是,这也不排除使用staticwith 属性。

于 2012-07-29T14:52:11.713 回答
21

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
于 2020-09-26T00:49:04.387 回答
16

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 反过来又要求Phones 变量。

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();
于 2020-07-15T14:40:14.180 回答
8

如前所述,主要区别之一是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::$namethenB::getName()将返回一个空字符串,因为这是在 Base 类中声明的内容。

于 2019-11-19T20:41:38.757 回答
6

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

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)
于 2020-08-24T13:08:46.103 回答