Доступ к некорректному статическому свойству из не статического метода в PHP

Я испытываю что-то в 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 ответа

Это на самом деле не ошибка, но, скорее, это результат, который не описан в документации. Я провел небольшое исследование и сам поиграл с несколькими вещами, и я думаю, что понял это, но я не могу быть уверен на 100%, так как нет официального текста, охватывающего это.

Создается впечатление, что когда вы пытаетесь вызвать статический метод для экземпляра, это равносильно использованию имени класса, и PHP фактически будет вызывать его именно так, а не для экземпляра. Например $B::getWhy(); такой же как B::getWhy()Это то, как основной код увидит это, независимо от того, передаете ли вы ему экземпляр или нет.

Проблема в том, что вы вызываете нестатический метод как статический метод. Из-за того, как методы работают, они требуют возможности для обеспечения таких вещей, как self а также $this, Теперь, вызывая нестатический метод, как если бы он был статическим, и учитывая вышеизложенное о том, как PHP будет фактически выполнять код, единственной доступной областью действия является область класса. A потому что это та сфера, из которой вы его называете. Это означает, что позднее статическое связывание имеет место и переопределяет B::$why с A::$why из-за изменения области действия, что именно то, чего должна достичь поздняя статическая привязка.

Я надеюсь, что это имеет смысл, если есть какие-то неясные моменты, дайте мне знать, и я сделаю все возможное, чтобы объяснить.

Для получения дополнительной информации, есть еще один вопрос, который на самом деле решает это: вызов нестатического метода с "::"

$B::bah(); должно быть $B->bah();, как bah не является статической функцией

Другие вопросы по тегам