[英]PHP: Sub class static inheritance - children share static variables?
如您在下面看到的,我有一个超类(Article)和两个子类。 我希望每个子类都有一个静态数组,该数组应包含所有对象。
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{}
-制作两个Report对象并将其添加到其数组中:
$tmp = new Report();
$tmp->add_Object_To_Array();
$tmp = new Report();
$tmp->add_Object_To_Array();
-制作两个Interview对象并将它们添加到其数组中:
$tmp = new Interview();
$tmp->add_Object_To_Array();
$tmp = new Interview();
$tmp->add_Object_To_Array();
print_r(Report::$articles);
print_r(Interview::$articles);
-上面的脚本列出了两个请求:
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(); }
如果您将静态变量声明视为定义类时运行的代码,则这实际上是有意义的。 当定义Article
类时,将创建一个静态变量并为其分配一个空数组。 定义了Interview
和Report
类后,就不会再发生这种情况。 只有一次分配了一个空数组-只有一个共享变量。
您在add_Object_To_Array()
方法中使用self
,而不是static
。
self::
引用它所定义的类,因此由于您的add_Object_To_Array()
方法是在Article
类中定义的,因此它将引用Article::$articles
数组。
static::
从PHP 5.3开始可用,并且引用它被调用的类。 这被称为后期静态绑定 ,这将导致add_Object_To_Array()
引用Report::$articles
或Interview::$articles
具体取决于调用对象的类型。
此代码将引用我们在第一步中声明的两个数组:
public function add_Object_To_Array() { array_push(static::$articles, $this); }
我以为我会提出一个替代解决方案,该解决方案会稍微更改您的设计,但不需要每个子类中的静态定义。 根据您的使用情况,这可能不是第一种解决方案更好的选择。
此解决方案使用get_class()
查找我们要存储的对象的类型,然后将其存储在父类中-在以类名为键的子数组中:
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版本一起使用,而不仅仅是PHP 5.3+。
当使用原始示例运行此版本时,将得到如下输出:
Array
(
[Report] => Array
(
[0] => Report Object
(
)
[1] => Report Object
(
)
)
[Interview] => Array
(
[0] => Interview Object
(
)
[1] => Interview Object
(
)
)
)
如果您确实有PHP 5.3或更高版本,则可以进一步扩展它,并使用get_called_class()
函数定义一个getInstances()
静态方法(在Article
类中),该方法的工作方式如下:
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());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.