Статическое наследование до PHP 5.3

class A
{
    static $v = "A";

    static function echoExtendedStaticVariable() {
        echo self::$v;
    }
}

class B extends A
{
    static $v = "B";
    // override A's variable with "B"
}

Почему:

echo B::$v

печатать "А"?

И как мне заставить его печатать "B"?

Есть ли способ сделать это до PHP 5.3?


person Alex V    schedule 20.12.2011    source источник
comment
Он не печатает «А», он печатает «В». Вы имели в виду $b = new B();$b->echoExtendedStaticVariable() === 'A'?   -  person Francis Avila    schedule 21.12.2011
comment
возможный дубликат PHP 5.2, эквивалентный поздней статической привязке (новый статический)?   -  person Naftali aka Neal    schedule 21.12.2011
comment
Я хочу сказать... ВСЕ ДОЛЖНО БЫТЬ СТАТИЧЕСКИМ.   -  person Alex V    schedule 21.12.2011
comment
Пожалуйста, отредактируйте свой исходный вопрос, чтобы точно указать, что вы хотите.   -  person Francis Avila    schedule 21.12.2011


Ответы (2)


B->echoExtendedStaticVariable() == 'A', потому что self:: вычисляется во время компиляции, а не во время выполнения. Это как если бы вы написали A:: вместо self::.

Что вам нужно, так это функция, называемая «поздним статическим связыванием» — она «поздняя», потому что она может определять класс во время выполнения, а не во время компиляции.

Вы можете эмулировать это (вроде) в PHP 5.2, используя ReflectionClass:

class A
{
    static $v = "A";
    function echoExtendedStaticVariable() {
        $rc = new ReflectionClass($this);
        echo $rc->getStaticPropertyValue('v');
    }
}
class B extends A
{
    static $v = "B";
}
$b = new B();
$b->echoExtendedStaticVariable(); // B

Обратите внимание, что вы можете сделать это, только если у вас есть доступ к экземпляру, поэтому вы не можете сделать echoExtendedStaticVariable статическим методом и ожидать, что он будет работать.

person Francis Avila    schedule 20.12.2011
comment
Есть ли другой способ сделать это без создания объекта? Просто запустить функцию в классе? - person Alex V; 21.12.2011
comment
Запуск какой функции в каком классе? В php ‹ 5.3 статический метод в родительском классе не может узнать, был ли он вызван статически через другой класс. Все имена разрешаются во время компиляции. и, как сказал @netcoder, это все равно не очень хороший дизайн! Что не так с использованием экземпляров? - person Francis Avila; 21.12.2011

В PHP 5.2 нет простого способа сделать это (т. е. без явного переопределения каждого метода).

Когда вы вызываете B::echoExtendedStaticVariable, он перенаправляется на A::echoExtendedStaticVariable, область действия изменяется на одну из A, и все привязки к B исчезают. Ни следа, ни отражения, ни магических констант, ничего: все указывает на A.

На мой взгляд, следует избегать статических членов, если в этом нет крайней необходимости, что бывает редко. Это затрудняет расширение вашего кода, поскольку внедрение зависимостей ограничено, а подстановка практически невозможна (за исключением анти- шаблонов, таких как Singleton).

person netcoder    schedule 21.12.2011