PHP无法覆盖受保护的静态方法

6

我似乎无法覆盖protected static变量。这很烦人,因为你也不能覆盖任何私有变量。我该怎么解决?(必须支持PHP 5.2)

<?
class Foo{
    protected static $stuff = 'Foo';
    public function showStuff(){
        echo self::$stuff . PHP_EOL;
    }
}

class Bar extends Foo{
    protected static $stuff = 'Bar';
}

$f = new Foo();
$b = new Bar();
$f->showStuff(); // Output: Foo
$b->showStuff(); // Output: Foo
?>
4个回答

19

你需要使用PHP 5.3中引入的一个功能,即后期静态绑定。在你的类Foo中,self指代Foo类本身。如果你想要指代调用发起的类,则需要使用关键词static

<?
class Foo{
    protected static $stuff = 'Foo';
    public function showStuff(){
        echo static::$stuff . PHP_EOL; // <-- this line
    }
}

class Bar extends Foo{
    protected static $stuff = 'Bar';
}

$f = new Foo();
$b = new Bar();
$f->showStuff(); // Output: Foo
$b->showStuff(); // Output: Bar
?>

这个方法难道不仅支持 PHP 5.3 吗? - Ibu
太棒了!我一直在寻找这个!可惜我的服务器还是5.2版本。 :( - GolezTrol
希望这会教你在问题中包含服务器版本。 - Lightness Races in Orbit
用 PHP 5.2 实现这个有什么方法吗? - Pwnna
很多人一直在等待PHP 5.3的这个功能,但我向你保证,在5.2中不需要等待即可实现。 - Matthieu Napoli
除了我下面发布的“解决方案”之外? - GolezTrol

3
你可以重写它们,但无法获取父类的值。这就是PHP所谓的覆盖,实际上是重新引入变量并尝试隐藏父变量。这就是为什么它不能按照你想要的方式工作的原因。
由于你还没有使用5.3,我认为最好的解决方案是也使用(并覆盖)静态函数。如果你不需要修改值,你可以让类重写函数以使其返回每个类的不同常量值。如果你需要变量,则可以在每个类中重新引入变量和函数。
class x
{
    static $a = '1';
    static function geta()
    {
        return self::$a;
    }
}

class y extends x
{
    static $a = '2';
    static function geta()
    {
        return self::$a;
    }
}

echo x::geta();
echo y::geta();

虽然有些糟糕,但它能解决问题,直到你可以使用更加简洁的 PHP 5.3 的 static:: 方法。


我正在提供一个 API。protected static 变量用于跟踪类的所有实例(当然是子类化的)。不同的子类具有不同的实例列表。我认为这对用户来说并不直观。 - Pwnna

1

有一个更好的解决方案。你可以使用get_called_class()来找到当前上下文,并用它来访问静态成员。 例如:

class Foo {
  protected static $table = "foo";
  static function getTable() {
    $class = get_called_class();
    return $class::$table;
  }
}
class Bar extends Foo {
  protected static $table = "bar";
}
echo Foo::getTable()."<br />\n";
echo Bar::getTable()."<br />\n";

您将获得以下输出:
foo<br />
bar<br />

那将适用于任何PHP 5版本


0

实际上你可以重写它们 :)

你只是不能在父类中使用它们,因为它们是静态的。后期静态绑定可以解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接