重写静态变量


override a static variable

我有两个类(Model和User),但我有一个问题,所以我试图用一个简单的例子来解释它:

class person
{
    protected static $todo ="nothing";
    public function __construct(){}
    public function get_what_todo()
    {
        echo self::$todo;
    }
}
class student extends person
{
    protected static $todo ="studing";
}
$s = new student();
$s->get_what_todo(); // this will show the word (nothing)
                     //but I want to show the word (studing)

请给我一个解决方案,但在学生课堂上不写任何函数的情况下,我只想在那里声明:)谢谢:)

该原理被称为"后期静态绑定",在PHP 5.3.0中引入;使用self关键字来访问在继承树内的调用类中定义的属性,或者使用static来访问在该继承树内子类中限定的属性。

class person
{
    protected static $todo ="nothing";
    public function __construct(){}
    public function get_what_todo()
    {
        echo static::$todo;  // change self:: to static::
    }
}
class student extends person
{
    protected static $todo ="studying";
}
class teacher extends person
{
    protected static $todo ="marking";
}
class guest extends person
{
}
$s = new student();
$s->get_what_todo(); // this will show the "studying" from the instantiated child class
$t = new teacher();
$t->get_what_todo(); // this will show the "marking" from the instantiated child class
$g = new guest();
$g->get_what_todo(); // this will show the "nothing" from the parent class,
                     // because $todo is not overriden in the child class

重写静态变量的可靠方法是通过重新声明它。有些人可能建议在构造方法中修改它,但我认为这不可靠。

在至少构造一次类之前,它不会反映更改。当然,在类方法中,不要忘记使用"静态::";而不是";self::";当您希望始终访问被重写的变量时。

以下是我的意思:Foo类是基类,Bar类在其构造函数中更改变量,Baz类在其声明中重写变量。

class Foo
{
    public static $a = "base";
}
class Bar extends Foo
{
    function __construct()
    {
        self::$a = "overridden";
    }
}
class Baz extends Foo
{
    public static $a = "overridden";
}
echo 'Foo: ' . Foo::$a . '<br>';
echo 'Bar: ' . Bar::$a . '<br>';
echo 'Baz: ' . Baz::$a . '<br>';
new Bar();
echo 'Bar after instantiation: ' . Bar::$a;

这是phptester.net 的输出

Foo: base
Bar: base
Baz: overridden
Bar after instantiation: overridden

正如您所看到的,Bar更改变量的方式直到构造函数被调用至少一次之后才会生效。

EDIT:但是,还有另一种方法可以永久可靠地编辑变量:在类声明之后进行编辑。如果您只需要修改一个变量而不完全覆盖它(例如数组),这就特别方便了。感觉有点脏,但理论上每次都应该有效。

class Foo
{
    public static $a = [
        'a' => 'a'
    ];
}
class Bar extends Foo
{
    public static $a;
}
Bar::$a = Foo::$a;
Bar::$a['b'] = 'b';
echo 'Foo: ' . print_r(Foo::$a, true) . '<br>';
echo 'Bar: ' . print_r(Bar::$a, true) . '<br>';

这是phptester.net 的输出

Foo: Array ( [a] => a )
Bar: Array ( [a] => a [b] => b ) 

编辑2:在我的测试中,ReflectionClass::getStaticPropertyValue也使用了最后一个方法

您可以尝试在构造中设置变量

class person
{
    protected static $todo = null;
    public function __construct(){
        self::$todo = "nothing";
    }
    public function get_what_todo()
    {
        echo self::$todo;
    }
}
class student extends person
{
    public function __construct() {
       self::$todo = "student";
    }
}
$s = new student();
$s->get_what_todo();

您可以尝试在构造中设置父变量

class person
{
    protected static $todo = null;
    public function __construct(){
        self::$todo = "nothing";
    }
    public function get_what_todo()
    {
        echo self::$todo;
    }
}
class student extends person
{
    public function __construct() {
       parent::$todo = "student";
    }
}
$s = new student();
$s->get_what_todo();