可以的。
foreach(new IteratorOne($obj) as $foo) ....
foreach(new IteratorTwo($obj) as $bar) .....
实际上,只要您的类实现了Iterator接口,您就可以将任意迭代器IteratorIterator应用于它。这是一件好事,因为应用元迭代器不需要知道与之相关的类的任何信息。
例如,考虑一个可迭代的类,像这样:
class JustList implements Iterator
{
function __construct() { $this->items = func_get_args(); }
function rewind() { return reset($this->items); }
function current() { return current($this->items); }
function key() { return key($this->items); }
function next() { return next($this->items); }
function valid() { return key($this->items) !== null; }
}
让我们定义一些元迭代器。
class OddIterator extends FilterIterator {
function accept() { return parent::current() % 2; }
}
class EvenIterator extends FilterIterator {
function accept() { return parent::current() % 2 == 0; }
}
现在将元迭代器应用于基类:
$list = new JustList(1, 2, 3, 4, 5, 6, 7, 8, 9);
foreach(new OddIterator($list) as $p) echo $p; // prints 13579
foreach(new EvenIterator($list) as $p) echo $p; // prints 2468
更新:PHP没有内部类,所以你可能需要使用eval,但这并不是一个好的解决方案。你需要将迭代器作为独立的类,这些类知道基类的结构。你可以在基类中提供方法,在后台实例化迭代器,从而减少对代码的影响:
class TreeDepthFirstIterator implements Iterator
{
function __construct($someTree).....
}
class Tree
{
function depthFirst() { return new TreeDepthFirstIterator($this); }
....
}
foreach($myTree->depthFirst() as $node).....
另一种选择是使用lambda表达式而不是foreach循环。这更加优雅和灵活,但需要PHP5.3以上版本:
class Tree
{
function depthFirst($func) {
while($node = .....)
$func($node);
.....
$myTree->depthFirst(function($node) {
echo $node->name;
});
yield return
的作用,或者给出一个使用案例的示例。 - Gordon