Да, вы можете.
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).....
Другой вариант - использовать лямбды вместо foreach. Это лучше и гибче, но требует php5.3:
class Tree
{
function depthFirst($func) {
while($node = .....)
$func($node);
.....
$myTree->depthFirst(function($node) {
echo $node->name;
});