覆盖静态变量

时间:2016-03-30 12:09:45

标签: php inheritance static-members

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

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)

请给我一个解决方案,但没有在学生班写任何功能我只想在那里做声明:)并且谢谢你:)

4 个答案:

答案 0 :(得分:8)

该原则称为“late static binding”,并在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 there is no override in the child class

答案 1 :(得分:3)

覆盖静态变量的可靠方法是通过重新声明它。有人可能会建议在构造方法中对其进行修改,但我认为这并不可靠。

直到至少构造一次该类,该更改才会反映出来。当然,在类方法中,当您要始终访问覆盖的变量时,请不要忘记使用“ static ::”而不是“ 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更改变量的方法直到至少一次调用构造函数之后才生效。

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

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在我的测试中也采用了最后一种方法。

答案 2 :(得分:2)

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

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();

答案 3 :(得分:1)

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

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();