看一下这个例子,并注意指示的输出。
<?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 来说是一种危险的行为,更多内容将在下面解释。)
对于为什么要这样做,我有以下两点考虑:
- 我不希望在所有子类中定义所有属性的冗余。
- 我希望将属性定义为父类中的默认值,并且我希望子类定义能够在需要时覆盖这些属性。每当需要使用默认值时,子类都需要排除属性,这就是为什么我没有在上面的示例中定义子类中的属性。
但是,如果我们想在运行时覆盖一个属性(通过 init 方法),它将为父类覆盖它!从那时起,较早初始化的子类(如 Brother 的情况)出乎意料地改变了你。
显然,这是因为子类没有自己的静态属性副本,只要它没有在子类内部显式定义 - 但不是抛出错误,而是切换静态行为以访问父类。因此,父类是否可以通过某种方式动态创建属于子类的属性,而不会出现在子类定义中?这样子类可以拥有自己的静态属性副本,并且静态关键字可以正确引用它,并且可以编写它以考虑父属性默认值。
还是有其他解决方案,好的、坏的或丑陋的?