PHP 5.3:后期静态绑定在父类中定义但在子类中丢失时对属性不起作用

时间:2011-01-02 04:51:09

标签: php oop php-5.3 late-static-binding

看看这个例子,注意显示的输出。

<?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. 我希望在父类中将属性定义为默认值,并且我希望子类定义能够在需要时覆盖这些属性。子类需要在默认情况下排除属性,这就是为什么我没有在上面的例子中定义子类中的属性。
  3. 但是,如果我们想要在运行时覆盖属性(通过init方法),它将为父类重写它!从那时起,早期初始化的子类(如兄弟的情况)意外地改变了你。

    显然,这是因为子类没有自己的静态属性副本,只要它没有在子类内部显式定义 - 而不是抛出错误,它会切换 static的行为访问父级。因此,是否有某种方式父类可以动态创建属于子类的属性而不显示在子类定义中?这样子类可以拥有自己的副本static属性和static关键字可以正确引用它,并且可以编写它以考虑父属性默认值。

    还是有其他解决方案,好的,坏的还是丑的?

1 个答案:

答案 0 :(得分:3)

它确实引用了正确的类,只是,除非重新声明或者引用集被破坏,否则子类中的静态属性与超类中的静态属性相同。

所以你必须这样做:

class Brother extends Mommy
{
    protected static $_data;
}

或:

class Brother extends Mommy
{
}

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