从PHP中的非静态方法中访问不正确的静态属性

时间:2013-12-17 19:27:45

标签: php late-static-binding

我在PHP中遇到的东西看起来很奇怪。我试图从非静态方法访问静态属性。我需要使用static关键字来访问此属性,因为它可以在每个子类中具有不同的值。

但是,它不是从期望的类中访问属性,而是从调用类访问该属性。这对我来说似乎是一个错误,但如果不是,我想知道是否有人可以向我解释这种行为,并解释我如何访问这个静态属性。

我的期望是静态属性$ why将从B类中获取。我很困惑为什么它会从A类中获取。

<?php

error_reporting(E_ALL & ~E_STRICT);

class A
{
    public static $why = "Really don't want this value. Bug?";
    public function callB()
    {
        $B = new B;
        $B::getWhy(); // PHP Bug? 
        $B->getWhy();
        $B::getWhyStatic();
        $B::getWhyStaticSelf();
    }
}

class Base {

    protected static $why = "Don't want this value";

    public static function getWhyStatic()
    {
        echo static::$why . "<BR>\n";    
    }

    public static function getWhyStaticSelf()
    {
        echo self::$why . "<BR>\n";    
    }

    public function getWhy()
    {
        echo static::$why . "<BR>\n";
    }
}

class B extends Base
{
    protected static $why = "Want this value?";
}

$A = new A;
$A->callB();

2 个答案:

答案 0 :(得分:2)

$B::bah();应为$B->bah();,因为bah不是静态函数。

答案 1 :(得分:2)

这不是一个真正的错误,但更多的结果并没有真正涵盖在文档中。我做了一些研究并且自己玩了一些东西,我想我已经弄清楚了,但我不能100%肯定,因为没有正式的文字涵盖这个。

我得到的印象是,当你试图在一个实例上调用静态方法时,它是使用类名的等价物,而PHP实际上会以这种方式调用它,而不是实例。例如,$B::getWhy();B::getWhy()相同,核心代码将如何看待它,无论您是否将实例传递给它。

您遇到的问题是您将非静态方法称为静态方法。由于方法的工作方式,它们需要一个范围来提供self$this等内容。现在,通过调用非静态方法就好像它是一个静态方法,并考虑上面关于PHP实际运行代码的方式,唯一可用的范围是类A,因为那是您调用它的范围。这意味着后期静态绑定发生并覆盖B::$whyA::$why,因为范围发生了变化,这正是后期静态绑定应该实现的目的。

我希望这是有道理的,如果有任何不清楚的地方,请告诉我,我会尽力解释。

有关更多信息,还有另一个问题实际解决了这个问题:Calling non static method with "::"