Статические переменные PHP в абстрактном родительском классе: вопрос в примере кода! - PullRequest
12 голосов
/ 01 апреля 2011

Быстрый код с включенным вопросом:

abstract class ClassParent {
    public static $var1 = "ClassParent";
}

class ClassChild1 extends ClassParent{
    public static function setvar1(){
        ClassChild1::$var1 = "ClassChild1";     
    }
}

class ClassChild2 extends ClassParent{
    public static function setvar1(){
        ClassChild2::$var1 = "ClassChild2";
    }
}


ClassChild1::setvar1();

echo ClassChild2::$var1;
// Returns "ClassChild1". Shouldn't this still be "ClassParent"?

Я предполагаю, что приведенное выше поведение является ожидаемым, а не ошибка PHP.В таком случае, как я могу объявить статическую переменную в родительском классе, которая будет обрабатываться отдельно для дочерних классов.Другими словами, я хочу иметь отдельные статические значения PER CLILD CLASS.Должен ли я объявить статическую переменную конкретно в дочерних классах или, может быть, есть другой способ?

Спасибо!

Ответы [ 2 ]

16 голосов
/ 01 апреля 2011

РЕДАКТИРОВАТЬ: При дальнейшем исследовании, я думаю, что вы спрашиваете, не представляется возможным напрямую, даже с поздним статическим связыванием. На самом деле, я немного удивлен.

Ответ на этот вопрос дает некоторые обходные пути.

Оригинальный ответ:


В родительском классе, если вы ссылаетесь на статическую переменную в форме:

self::$var

Он будет использовать эту же переменную во всех унаследованных классах (поэтому все дочерние классы будут по-прежнему обращаться к переменной в родительском классе).

Это связано с тем, что привязка для ключевого слова self выполняется во время компиляции, а не во время выполнения.

Начиная с PHP 5.3, PHP поддерживает позднюю статическую привязку с использованием ключевого слова static. Итак, в ваших классах обращайтесь к переменной с помощью:

static::$var

И «static» будет разрешен дочернему классу во время выполнения, поэтому для каждого дочернего класса будет отдельная статическая переменная.

3 голосов
/ 24 октября 2011

Спасибо за этот вопрос! У меня были некоторые проблемы, которые я не мог отследить, и это помогло мне решить их. :)

Возможно, вам будет интересно узнать, что отчет об ошибке для этого поведения включает обходной путь. В вашем случае это будет:

class ClassChild1 extends ClassParent{
    public static function setvar1(){
        $tmp = 'x';
        static::$var1 =& $tmp; // break reference
        // and now this works as expected: (changes only ClassChild1::$var1)
        static::$var1 = "ClassChild1";     
    }
}
// do the same in ClassChild2...

Ужасно, черт возьми, я согласен - но PHP работает так, как и ожидалось, плюс у него нет побочных эффектов.

Это действительно очень сомнительная (и плохо документированная) "особенность" в моих глазах - будем надеяться, что они когда-нибудь ее изменят.

...