PHP:子类静态继承-子类共享静态变量?

PHP:子类静态继承-子类共享静态变量?,php,inheritance,static,subclass,extend,Php,Inheritance,Static,Subclass,Extend,正如您在下面看到的,我有一个超级类(文章)和两个子类。我希望每个子类都有一个静态数组,该数组将容纳它的所有对象 abstract class Article { public static $articles = array(); // Variable for storing all the objects of each sub-class. public function add_Object_To_Array() { array_p

正如您在下面看到的,我有一个超级类(文章)和两个子类。我希望每个子类都有一个静态数组,该数组将容纳它的所有对象

abstract class Article
{
    public static $articles = array(); // Variable for storing all the objects of each sub-class.

    public function add_Object_To_Array()
    {       
        array_push(self::$articles, $this);
    }
}

class Report extends Article{}
class Interview extends Article{}
-创建两个报表对象并将其添加到其数组:

$tmp = new Report();
$tmp->add_Object_To_Array();

$tmp = new Report();
$tmp->add_Object_To_Array();
$tmp = new Interview();
$tmp->add_Object_To_Array();

$tmp = new Interview();
$tmp->add_Object_To_Array();

print_r(Report::$articles);
print_r(Interview::$articles);
-制作两个访谈对象并将其添加到其数组中:

$tmp = new Report();
$tmp->add_Object_To_Array();

$tmp = new Report();
$tmp->add_Object_To_Array();
$tmp = new Interview();
$tmp->add_Object_To_Array();

$tmp = new Interview();
$tmp->add_Object_To_Array();

print_r(Report::$articles);
print_r(Interview::$articles);
-上面的脚本给出了两个Aray:

Array
(
    [0] => Report Object()

    [1] => Report Object()

    [2] => Interview Object()

    [3] => Interview Object()   
)
Array
(
    [0] => Report Object()

    [1] => Report Object()

    [2] => Interview Object()

    [3] => Interview Object()    
)
如果你问我,这看起来很相似,但第一个应该只包含报告,第二个只包含采访

1。似乎只有一个数组,为什么只有一个数组?
2。我在同一个类中有一个静态的对象容器,这是错误的编码吗?(有什么建议吗?


我对php非常陌生,但有java背景。

所有东西都只进入一个数组,原因有二:

  • $articles
    属性仅在
    Article
    类中定义

    如果您习惯于非静态属性,那么静态类属性不会以您可能期望的方式继承。虽然它们对子类可用,但它们仍然引用父类上的单个变量-导致您在这里看到的两个子类共享同一数组的行为

    防止这种情况的唯一方法是在每个子类中定义一个单独的数组,如下所示:

    class Report extends Article {
        public static $articles = array();
    }
    class Interview extends Article {
        public static $articles = array();
    }
    
    public static function getInstances()
    {
        $class = get_called_class();
        // return isset(self::$articles[$class]) ? self::$articles[$class] : array();
        if (isset(self::$articles[$class])) {
            return self::$articles[$class];
        } else {
            return array();
        }
    }
    
    print_r(Report::getInstances());
    print_r(Interview::getInstances());
    
    如果您认为静态变量声明是在定义类时运行的代码,那么这实际上是有意义的。定义
    项目
    类时,会创建静态变量并为其分配空数组。当定义了
    访谈
    报告
    类时,这种情况不会再次发生。只有一次空数组被赋值-只有一个共享变量

  • 您在
    将对象添加到数组()
    方法中使用的是
    self
    ,而不是
    static

    • self::
      引用它在中定义的类,因此,由于您的
      add_Object_to_Array()
      方法是在
      Article
      类中定义的,因此它将引用
      Article::$articles
      数组

    • static::
      在PHP5.3中开始提供,并引用调用它的类。这称为,并将导致
      将对象添加到数组()
      引用
      报告::$articles
      访谈::$articles
      ,具体取决于调用对象的类型

    此代码将引用我们在第一步中声明的两个数组:

    public function add_Object_To_Array() {
        array_push(static::$articles, $this);
    }
    

  • 我想我会提供一个替代的解决方案,稍微改变一下您的设计,但不需要在每个子类中进行静态定义。根据您的使用情况,这可能比第一个解决方案更好,也可能不是

    此解决方案用于查找我们要存储的对象的类型,然后将其存储在父类中-在由classname键入的子数组中:

    abstract class Article
    {
        public static $articles = array();
    
        public function add_Object_To_Array()
        {
            // get the actual class of the current object
            $class = get_class($this);
            // define an empty subarray for this class if we haven't seen it before
            if (!isset(self::$articles[$class])) {
                self::$articles[$class] = array();
            }
            // add this object to the appropriate subarray
            array_push(self::$articles[$class], $this);
        }
    }
    class Report extends Article{}
    class Interview extends Article{}
    
    上面的代码不使用后期静态绑定,因此它可以用于任何PHP版本,而不仅仅是PHP5.3+

    使用原始示例运行此版本时,将得到如下输出:

    class Report extends Article {
        public static $articles = array();
    }
    class Interview extends Article {
        public static $articles = array();
    }
    
    public static function getInstances()
    {
        $class = get_called_class();
        // return isset(self::$articles[$class]) ? self::$articles[$class] : array();
        if (isset(self::$articles[$class])) {
            return self::$articles[$class];
        } else {
            return array();
        }
    }
    
    print_r(Report::getInstances());
    print_r(Interview::getInstances());
    
    数组
    (
    [报告]=>阵列
    (
    [0]=>报告对象
    (
    )
    [1] =>报告对象
    (
    )
    )
    [采访]=>数组
    (
    [0]=>采访对象
    (
    )
    [1] =>采访对象
    (
    )
    )
    )
    
    如果您使用的是PHP 5.3或更高版本,则可以进一步扩展此功能,并使用此函数定义一个
    getInstances()
    静态方法(在
    文章
    类中),其工作方式如下:

    class Report extends Article {
        public static $articles = array();
    }
    class Interview extends Article {
        public static $articles = array();
    }
    
    public static function getInstances()
    {
        $class = get_called_class();
        // return isset(self::$articles[$class]) ? self::$articles[$class] : array();
        if (isset(self::$articles[$class])) {
            return self::$articles[$class];
        } else {
            return array();
        }
    }
    
    print_r(Report::getInstances());
    print_r(Interview::getInstances());
    
    然后您可以在示例中调用此方法,如下所示:

    class Report extends Article {
        public static $articles = array();
    }
    class Interview extends Article {
        public static $articles = array();
    }
    
    public static function getInstances()
    {
        $class = get_called_class();
        // return isset(self::$articles[$class]) ? self::$articles[$class] : array();
        if (isset(self::$articles[$class])) {
            return self::$articles[$class];
        } else {
            return array();
        }
    }
    
    print_r(Report::getInstances());
    print_r(Interview::getInstances());
    

    抽象类文章
    缺少结尾}
    $该
    在该上下文中指的是
    抽象类文章
    。您将如何将其应用到阵列中?谢谢,但我想:
    $tmp=new Report()$tmp->add_Object_To_Array()引用了“报表对象的函数”?(面向对象的思考)。我知道抽象类不能有对象。使用
    static::$articles
    而不是
    self::$articles
    谢谢,但我已经尝试过了,它不起作用。@AlexP
    static::
    是必需的,但它只是解决方案的一部分。您还需要单独定义变量。非常感谢!很好的回答,包括教育和解决问题!:)美好的我没有完全理解您的扩展方法,更准确地说,
    返回isset(self::$articles[$class])?self::$articles[$class]:数组(),我不太熟悉这种类型的if语句。如果语句为
    false
    ,它是否返回空数组?@MathiasCiarlo我使用的是there。我把它改写成了一个更清晰但本质上相同的版本。