【发布时间】:2011-03-12 08:32:20
【问题描述】:
我正在用 PHP 5.3 编写一个库,其中大部分是一个具有多个静态属性的类,这些静态属性由子类扩展以允许子类的零配置。
无论如何,这里有一个示例来说明我发现的特殊性:
<?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'
谁能解释这是为什么?我无法理解引用如何以任何方式影响静态继承:/
更新:
基于Artefacto's answer,在基类(在本例中为A)中具有以下方法并在类声明后调用它会产生上面标记为“期望”的行为,而无需在setter中通过引用分配,同时在使用 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();
/*...*/
【问题讨论】:
-
这很有趣;我不知道。除非有人想出答案,否则你会让我浪费时间调查它:p
-
可能与 5.3 的新后期静态绑定有关
-
另外,使用
get_call_class()而不是$v不起作用,因为它不能通过引用分配。但是,使用中间变量作为参考的工作方式如上。 -
@John Conde:问题是后期静态绑定语法 (
static::$a) 用于这两种情况,但考虑到后期静态绑定的目标,我会考虑预期的结果。 -
出于好奇,B 和 C 是 A 的实际特化,还是 A 是所有类都将从中继承的某种基本上帝对象,无论它们是否相关。
标签: php inheritance reference php-5.3