更改对象状态/内容适当的迭代器使用(php)

时间:2011-07-12 16:29:56

标签: php iterator

考虑用于存储项目集合的对象,但该集合可能会因预定义的上下文而异。

Class Container implements IteratorAggregate (
  protected $contexts; // list of associated contexts, example: array(0=>1,1=>3)
  protected $contents; // array
  public loadContents( $contextId ) { /* populates $this->contents*/ }
  public getContexts() { /* populates $this->contexts */ }
  ...
  public function getIterator() { return new ArrayIterator($this->contents); }
  public getContextIterator() { return new contextIterator($this); }
}

迭代器看起来像:

Class contextIterator {
  protected $container;
  protected $contexts;
  protected $currentContext;

  public function __construct($container) {
    $this->container = $container;
    $this->contexts = $container->getContexts();
    $this->currentContext = 0;
  }

  public current() {
    $this->container->loadContents( $this->key() );
    return $this->contexts[ $this->key() ];
  }

  public function key() { return $this->currentContext; }
  public function next() { $this->currentContext++; }
  public function rewind() { $this->currentContext = 0; }
  public function valid() { return isset( $this->contexts[ $this->key() ] ); }
}

对于需要迭代检查每个上下文的少数情况,我会执行以下操作:

$myContainer = new Container();
foreach( $myContainer->getContextIterator() as $key => $value ) {
  $myContainer->someMethod();
}

以上是好的和紧凑的,但它对我来说很脏,因为我从来没有真正使用$ key或$ value。使用迭代器是否过度杀伤?此外,迭代器是否应该更改它正在迭代的对象的状态/内容?

1 个答案:

答案 0 :(得分:1)

  

以上是好的和紧凑的,但我感觉很脏,因为我从来没有真正使用$ key或$ value。

您尚未展示getContextIterator()的内容,因此很难提出具体建议。通常,可以通过实现OuterIterator interace或仅实现Iterator interface来在PHP中创建可迭代的对象。这两个界面都是预定义的,然后您可以将对象与next()foreach等一起使用。

我假设你已经实现了像 OuterIterator这样的。如果您实施OuterIterator,您将获得AFAIK的速度优势。

  

使用迭代器是否过度杀伤?

不,不会这么说。迭代器非常适合收藏,因为你说你有一个。我只是将它改成SPL迭代器。

  

此外,迭代器是否应该更改正在迭代的对象的状态/内容?

实际上每个迭代器都有,至少对于迭代的内部指针。但我认为这不是你的担忧,但可能已经减轻了。

因此,即使对于你正在迭代的对象内部的“更多”变化,只要它清楚它的作用,它就完全可以改变。反例:如果你遍历一个数组,每次迭代前进一步就会改变元素是没用的。

但是在其他情况下,这是完全有效的。所以决定做了什么,而不是一般规则。