【问题标题】:How do I iterate over instances of a class如何迭代类的实例
【发布时间】:2012-02-16 20:39:35
【问题描述】:

有没有办法在 PHP 中遍历一个类的所有实例?我可以通过在创建它们时使用静态变量对它们进行计数来手动完成,但我更希望能够创建一个适用于类的每个实例的静态方法。

例如,假设我有一个名为 Ball 的类,它通过其构造函数为每个球创建一个唯一 ID 和一组特征。 Ball 类有一个方法可以通过名为 getCSSrule() 的方法为特定的球生成 CSS。我想创建一个名为 getCSS() 的静态方法,该方法将为每个现有的球调用 getCSSrule(),为当前存在的所有球写出整个 CSS 块。然后,我可以只调用 Ball::getCSS() 一次,而不是为每个球调用 $obj->getCSSrule()。

public static function getCSS(){
  $css;
  foreach(Ball as $obj){
    $css += $obj->getCSSrule();
  }
  return $css;
}

foreach 似乎既不能作为类中的静态方法工作,也不能作为类外的函数工作。目前我必须制作一个球名数组并使用它来查找该类的每个实例。谢谢!

【问题讨论】:

  • 我很难理解你想要做什么。请澄清问题。也许删除所有实现细节,只说明你的设置/场景以及你想要的输出/目标是什么。
  • 看起来类似于this question
  • 很好找 parkker007,我错过了那个。
  • 谢谢戈登。你很好地回答了我的问题。您的第一种方法效果很好,当我的声誉允许我这样做时,我会投票给它......我也非常喜欢第二种方法,并将很快对其进行测试。

标签: php oop


【解决方案1】:

目前我必须创建一个包含球名称的数组并使用它来查找该类的每个实例。

这是实现您想要做的事情的正确方法。稍微多一点的 OO 方法会使用某种集合类(例如,BallPit,如 Daff 的回答中所述),但原理是相同的。

还有其他方法,例如创建一种混合 multiton(与传统的 multiton 不同,它不会限制可以创建的实例数量,但只能通过拥有类的静态方法,它将管理创建的实例数组。

但是,如果您正在(或可能有一天)为您的应用程序使用自动化测试,那将会给您带来极大的麻烦。

【讨论】:

    【解决方案2】:

    嗯,我很确定您必须以某种方式在某处跟踪实际实例(而不仅仅是它们的名称)。例如。在类 BallPit 或包含球列表的主脚本中。这也是您遍历列表并获取每个实例 CSS 的地方。

    【讨论】:

      【解决方案3】:

      根据您给定的实现细节的字面答案将类似于

      class Ball
      {
          protected static $balls = array();
          protected $cssRule;
      
          public function __construct($cssRule)
          {
              self::$balls[] = $this;
              $this->cssRule = $cssRule;
          }
          public static function getCss()
          {
              $css = '';
              foreach (self::$balls as $ball) {
                  $css .= $ball->getCssRule();
              }
              return $css;
          }
          public function getCssRule()
          {
              return $this->cssRule;
          }
      }
      

      换句话说,您可以在静态属性中收集创建的实例。然后你可以做你在问题中要求的,例如(demo)

      new Ball('foo');
      new Ball('bar');
      new Ball('baz');
      echo Ball::getCSS();
      

      然后会打印 foobarbaz。这是否是一个好方法是一个不同的问题。我更喜欢的替代方案是这样的:

      class Balls implements IteratorAggregate
      {
          protected $balls;
      
          public function __construct()
          {
              $this->balls = new SplObjectStorage;
          }
          public function attach(Ball $ball)
          {
              $this->balls->attach($ball);
          }
          public function detach(Ball $ball)
          {
              $this->balls->detach($ball);
          }
          public function getIterator()
          {
              return clone($this->balls);
          }
          public function create($cssRule)
          {
              $ball = new Ball($cssRule);
              $this->attach($ball);
              return $ball;
          }
      }
      

      你可以这样做

      $balls = new Balls;
      $balls->create('foo');
      $balls->create('bar');
      $balls->create('baz');
      

      创建新的Ball 实例,该实例将自动存储在Balls 中。因为BallsIteratorAggregate,你可以简单地使用foreach 遍历所有实例,例如

      $css = '';
      foreach($balls as $ball) {
          $css .= $ball->getCssRule();
      }
      echo $css;
      

      当然,您也可以将该代码移动到Balls 中的实例方法中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-05
        • 2021-08-12
        • 2022-10-18
        • 2020-11-25
        • 1970-01-01
        • 1970-01-01
        • 2015-11-28
        • 2019-04-26
        相关资源
        最近更新 更多