【问题标题】:override a static variable覆盖静态变量
【发布时间】:2016-03-30 12:09:45
【问题描述】:

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

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)

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

【问题讨论】:

  • Late static binding.....echo self::$todo;echo static::$todo;之间的区别
  • 非常感谢你,你刚刚救了我的命,如果你愿意,可以添加你的评论作为答案:) :)

标签: php inheritance static-members


【解决方案1】:

该原理称为“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 $todo is not overriden in the child class

【讨论】:

    【解决方案2】:

    重写静态变量的可靠方法是重新声明它。可能有人会建议在construct方法中修改,但我觉得不靠谱。

    在类至少构造一次之前,它不会反映更改。当然,在类方法中,当您想始终访问被覆盖的变量时,不要忘记使用“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 在我的测试中也采用了最后一种方法。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-22
          • 1970-01-01
          • 2013-10-27
          • 2010-10-10
          • 1970-01-01
          • 2016-03-03
          • 1970-01-01
          相关资源
          最近更新 更多