考虑用于存储项目集合的对象,但该集合可能会因预定义的上下文而异。
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。使用迭代器是否过度杀伤?此外,迭代器是否应该更改它正在迭代的对象的状态/内容?
答案 0 :(得分:1)
以上是好的和紧凑的,但我感觉很脏,因为我从来没有真正使用$ key或$ value。
您尚未展示getContextIterator()
的内容,因此很难提出具体建议。通常,可以通过实现OuterIterator
interace或仅实现Iterator
interface来在PHP中创建可迭代的对象。这两个界面都是预定义的,然后您可以将对象与next()
,foreach
等一起使用。
我假设你已经实现了像 OuterIterator
这样的。如果您实施OuterIterator
,您将获得AFAIK的速度优势。
不,不会这么说。迭代器非常适合收藏,因为你说你有一个。我只是将它改成SPL迭代器。使用迭代器是否过度杀伤?
此外,迭代器是否应该更改正在迭代的对象的状态/内容?
实际上每个迭代器都有,至少对于迭代的内部指针。但我认为这不是你的担忧,但可能已经减轻了。
因此,即使对于你正在迭代的对象内部的“更多”变化,只要它清楚它的作用,它就完全可以改变。反例:如果你遍历一个数组,每次迭代前进一步就会改变元素是没用的。
但是在其他情况下,这是完全有效的。所以决定做了什么,而不是一般规则。