Я пишу библиотеку в PHP 5.3, основная часть которой представляет собой класс с несколькими статическими свойствами, который расширяется из подклассов, чтобы позволить zero-conf для дочерних классов.
В любом случае, здесь образец, чтобы проиллюстрировать обнаруженную мной особенность:
<?php
class A {
protected static $a;
public static function out() { var_dump(static::$a); }
public static function setup($v) { static::$a =& $v; }
}
class B extends A {}
class C extends A {}
A::setup('A');
A::out(); // 'A'
B::out(); // null
C::out(); // null
B::setup('B');
A::out(); // 'A'
B::out(); // 'B'
C::out(); // null
C::setup('C');
A::out(); // 'A'
B::out(); // 'B'
C::out(); // 'C'
?>
Теперь это довольно желаемое поведение для статического наследования, насколько мне известно, однако, меняя static::$a =& $v;
на static::$a = $v;
(без ссылки), вы получаете ожидаемое поведение, то есть:
'A'
'A'
'A'
'B'
'B'
'B'
'C'
'C'
'C'
Может кто-нибудь объяснить, почему это? Я не могу понять, как ссылки влияют на статическое наследование любым способом:/
Update:
Основанный на ответе Artefacto, имеющий следующий метод в базовом классе (в данном случае, A) и вызывающий его после объявления класса, создает поведение, обозначенное как ' желательно "выше" без необходимости назначать по ссылке в сеттерах, оставляя результаты при использовании self:: как "ожидаемое" поведение выше.
/*...*/
public static function break_static_references() {
$self = new ReflectionClass(get_called_class());
foreach($self->getStaticProperties() as $var => $val)
static::$$var =& $val;
}
/*...*/
A::break_static_references();
B::break_static_references();
C::break_static_references();
/*...*/