PHP 5.3: Позднее статическое связывание не работает для свойств, если оно определено в родительском классе, но отсутствует в дочернем классе. - PullRequest
10 голосов
/ 02 января 2011

Посмотрите на этот пример и обратите внимание на указанные результаты.

<?php

class Mommy
{
    protected static $_data = "Mommy Data";

    public static function init( $data )
    {
        static::$_data = $data;
    }

    public static function showData()
    {
        echo static::$_data . "<br>";
    }
}

class Brother extends Mommy
{
}

class Sister extends Mommy
{
}

Brother::init( "Brother Data" );
Sister::init( "Sister Data" );

Brother::showData(); // Outputs: Sister Data
Sister::showData(); // Outputs: Sister Data

?>

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

Я имею в виду следующие две вещи, почему я хочу это сделать:

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

Однако, если мы хотим переопределить свойство во время выполнения (через метод init), оно переопределит его для родительского класса! С этого момента дочерние классы, инициализированные ранее (как в случае с Brother), неожиданно меняются.

Очевидно, это результат того, что дочерние классы не имеют своей собственной копии статического свойства, если оно не определено явно внутри дочернего класса - но вместо того, чтобы выдавать ошибку, оно переключает поведение static для доступа к родителю. Следовательно, существует ли способ, которым родительский класс мог бы динамически создавать свойство, принадлежащее дочернему классу, без его появления в определении дочернего класса? Таким образом, дочерний класс мог иметь свою собственную копию статического свойство и ключевое слово static могут ссылаться на него должным образом, и его можно записать с учетом значений по умолчанию родительского свойства.

Или есть какое-то другое решение, хорошее, плохое или безобразное?

1 Ответ

4 голосов
/ 02 января 2011

Это относится к правильному классу, просто, если не объявлено повторно или не нарушен набор ссылок, статические свойства в подклассах находятся в том же наборе ссылок, что и в суперклассе.

Так что вы должны сделать:

class Brother extends Mommy
{
    protected static $_data;
}

или:

class Brother extends Mommy
{
}

$tmp = null;
Brother::$_data =& $tmp;
unset($tmp);
...