在PHP中,self::$bar和static::$bar之间有什么区别?

14 浏览
0 Comments

在PHP中,self::$bar和static::$bar之间有什么区别?

在下面的示例中,使用selfstatic有什么区别?\n

class Foo
{
    protected static $bar = 1234;
    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }
}
Foo::instance();

\n

输出结果如下:

\n

1234
1234

\n使用self关键字时,引用的是当前类的静态属性$bar。使用static关键字时,引用的是调用该方法的类的静态属性$bar。在这个例子中,Foo::instance()是由类Foo调用的,所以无论是使用self还是static,都引用的是Foo类的静态属性$bar,所以输出结果相同。

0
0 Comments

在上面的代码示例中,我们可以看到,尽管我们在Fax类中覆盖了$number变量,但getNumber()仍然返回123。这是因为我们要求PHP返回变量在哪里定义的,它将返回Phone类的变量。

如果我们将self调用换成static,我们将得到Fax类的覆盖值:

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();

这是一个非常直观和不会引起混淆的示例。

问题的原因是使用self关键字时,PHP将返回变量在哪个类中定义的,而不是在哪个类中调用的。因此,self::$number返回的是Phone类中的$number变量,而不是Fax类中的。

为了解决这个问题,我们可以使用static关键字。使用static::$number将返回在当前类中定义的$number变量,而不管是在父类还是子类中定义的。

这种区别在继承和多态的情况下特别重要。通过使用static关键字,我们可以确保在子类中覆盖父类的变量时,调用正确的变量值。

0
0 Comments

这个问题的出现是因为在PHP中,使用self::$barstatic::$bar时,会有不同的结果。以下是一个简单的示例来展示它们之间的区别:

class A { // 基类
    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

在上面的示例中,类A定义了一个静态属性$name,并且有两个静态方法getSelfName()getStaticName()。其中getSelfName()使用self::$name来访问静态属性,而getStaticName()使用static::$name来访问静态属性。

当我们调用A::getSelfName()时,它返回的是ClassA,因为self::$name指向的是A类自身的静态属性。

同样地,当我们调用A::getStaticName()时,它也返回的是ClassA。这是因为static::$name在这里也指向A类自身的静态属性。

然而,当我们调用B::getSelfName()时,它仍然返回的是ClassA,而不是ClassB。这是因为self::$name指向的是定义这个属性的类自身,即A类。

但是,当我们调用B::getStaticName()时,它返回的是ClassB。这是因为static::$name在这里指向的是调用这个方法的类,即B类。

为了解决这个问题,我们可以使用static关键字来实现后期静态绑定。这样,static::$bar将根据调用方法的类来确定属性的值。这样,我们就可以在子类中正确地访问静态属性。

总结起来,self::$bar始终指向定义这个属性的类自身,而static::$bar会根据调用方法的类来确定属性的值。这种区别在使用继承和静态属性时很重要,可以确保在子类中正确访问静态属性。

0
0 Comments

在PHP中,使用`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`关键字调用后期绑定构造函数的示例,可以参考这个相关问题:[New self vs. new static](https://stackoverflow.com/questions/5197300)

然而,这并不排除使用`static`来处理属性的可能性。在子类中很容易重新声明父类的属性,父类的属性可能是子类使用的默认值,除非它们重新声明。如果你在父类中,我猜使用`self`是安全的;如果在子类中,你可以找到一个使用任何一个的理由,但是如果你不希望重新声明,`self`也可以工作。

去[phpfiddle.org](http://phpfiddle.org/)运行下面的代码:

a();
?>

前两段文字表达不清晰,存在一个含糊不清的代词"it",而且也有冗余的部分,因为后面的段落更清楚地解释了相同的信息。建议用后面以"In the above scenario"开头的段落替换前两个段落,这样底线的简洁答案就在最前面。这样更清晰和易于理解。

另一种思考方式:`self::$abc`在`class Foo`内部使用时,等同于`Foo::$abc`。它不会受到子类中`$abc`的重新声明的影响。据我所知,使用`self`的唯一理由是作为一种简写,避免使用可能更长的类名`Foo`。[它也意味着你可以在不改变所有使用的地方的情况下更改类名 - 但在我看来,这并不是一个很好的理由。](PHP的命名选择不太幸运,似乎是相反的;"static"可以改变 - 这与自然语言中"static"的意思相反。)

0