为什么分配对静态类变量的引用会破坏这种变量的继承?

时间:2015-04-28 23:32:05

标签: php inheritance reference static

我不明白为什么在下面的代码中,$ my_foo和$ my_bar被子类正确继承,但如果我通过赋予$ my_var的引用来更改$ my_foo,则子类仍会看到原始价值..

  <?php
    class Foo
    {
        public static $my_foo = 'foo';
        public static $my_bar = 'bar';

        public static function break_inheritance() {
            self::$my_bar = &self::$my_foo;
        }

        public static function foo_print_vars() {
            print self::$my_foo." ";
            print self::$my_bar."\n";
        }
    }

    class Bar extends Foo
    {
        public static function bar_print_vars() {
            print self::$my_foo." ";
            print self::$my_bar."\n";
        }
    }


    Bar::bar_print_vars(); // OUTPUTS foo bar
    Foo::break_inheritance(); 
    Foo::foo_print_vars(); // OUTPUTS foo foo
    Bar::bar_print_vars(); // OUTPUTS foo bar

编辑:这是一个类似的问题:do extended classes inherit static var values (PHP)?但我的更专注于继承和引用。

EDIT2:请注意,这个问题的重点不在于后期静态绑定,但这就是为什么,因为$ my_foo和$ my_bar是继承的,在Foo中更改它们并不会影响它们在酒吧。而仅在参考时发生。事实上,如果我们改变:

 public static function break_inheritance() {
            self::$my_bar = self::$my_foo; // removed reference in assignment
        }

行为完全改变,最后一个Bar :: bar_print_vars(); // OUTPUTS foo foo

3 个答案:

答案 0 :(得分:0)

Foo与Bar不同。尝试拨打Bar::break_inheritance();,看看会发生什么。

答案 1 :(得分:0)

将类的静态属性视为具有奇特名称的全局变量。

class Foo
{
    public static $my_foo = 'foo';
    public static $my_bar = 'bar';
    // ...
}

上面的代码声明了类Foo的两个静态属性,其全名为Foo::$my_fooFoo::$my_bar

通过扩展Foo,类Bar会生成另外两个名为Bar::$my_fooBar::$my_bar的静态属性。

代码:

class Foo
{
    public static function break_inheritance() {
        self::$my_bar = &self::$my_foo;
    }
}
Foo::break_inheritance(); 

修改Foo::$my_bar。它不会影响Bar::$my_bar

如果你把它称为:

Bar::break_inheritance(); 

它仍会更改Foo::$my_bar,但不会影响Bar::$my_bar

使用self::的引用在编译时绑定到使用它的类的属性。它与您编写Foo::$my_bar = &Foo::$my_foo;的内容相同。无论您如何调用方法break_inheritance(),它都会始终修改Foo::$my_bar

如果您想使用方法break_inheritance()更改Bar::$my_bar,则必须将其更改为使用static::而不是self::

class Foo
{
    public static function break_inheritance() {
        static::$my_bar = &static::$my_foo;
    }
}
Foo::break_inheritance();         // Changes `Foo::$my_bar`
Bar::break_inheritance();         // Changes `Bar::$my_bar`

这称为late static binding,已在PHP 5.3中引入。

后期静态绑定(static::)对类属性和方法的工作方式与$this->对常规属性和方法的工作方式相同。它使用在您使用它的类中定义的属性或方法(在子类中),如果有的话,而不是从父类继承的属性或方法。

答案 2 :(得分:0)

这是因为PHP 5.3.0版中引入了一个名为Late static binding的新功能。

Late static binding来自于static ::不会使用定义方法的类来解析,而是使用运行时信息来计算。