php - When does the NoRewindIterator rewind the inner Iterator? -
by name clear when php's norewinditerator rewinds: never.
but sometimes, esp. when extending it, ask myself: ever rewind? rewind once? if need it, need implement (first) rewind traversable might require it?
i wonder inner iterator here, iterator norewinditerator class takes parameter constructor.
for example:
$iterator = new someiterator(); // implements iterator $norewind = new norewinditerator($iterator); foreach ($norewind $value) { break; } will $iterator->rewind() never called when using $norewind here on? or called once first time $norewind->rewind() invoked (e.g. within first foreach in example). or maybe on construct?
like name of class alone (norewinditerator), the manual has following wording in specific:
norewinditerator - iterator cannot rewound.
and concrete method:
norewinditerator::rewind() - prevents rewind operation on inner iterator.
this implies iterator::rewind() method not passed through inner iterator. tests show this, here simple 1 i've been running (code of iterators not part of php in iterator garden):
$iterator = new rangeiterator(1, 1); $debug = new debugiteratordecorator($iterator); $norewind = new norewinditerator($debug); echo "first foreach:\n"; foreach ($norewind $value) { echo "iteration value: $value\n"; } in code, debug-iterator prints (echoes) iteration information on fly:
first foreach: iterating (rangeiterator): #0 valid() iterating (rangeiterator): #0 parent::valid() true iterating (rangeiterator): #0 current() iterating (rangeiterator): #0 parent::current() 1 iteration value: 1 iterating (rangeiterator): #1 next() iterating (rangeiterator): #1 after parent::next() iterating (rangeiterator): #1 valid() iterating (rangeiterator): #1 parent::valid() false as shows, $iterator->rewind() never called.
this makes sense same reasons given in related question: why must rewind iteratoriterator. norewinditerator extends iteratoriterator , different it's parent class, getinneriterator() method returns iterator , not traversable.
this change allows initialize rewind when need to:
echo "\n\$calling norewind->getinneriterator()->rewind():\n"; $norewind->getinneriterator()->rewind(); echo "\nsecond foreach:\n"; foreach ($norewind $value) { echo "iteration value: $value\n"; } exemplary debug output again:
$calling norewind->getinneriterator()->rewind(): iterating (rangeiterator): #0 rewind() iterating (rangeiterator): #0 after parent::rewind() second foreach: iterating (rangeiterator): #0 valid() iterating (rangeiterator): #0 parent::valid() true iterating (rangeiterator): #0 current() iterating (rangeiterator): #0 parent::current() 1 iteration value: 1 iterating (rangeiterator): #1 next() iterating (rangeiterator): #1 after parent::next() iterating (rangeiterator): #1 valid() iterating (rangeiterator): #1 parent::valid() false knowing these details allow create onetimerewinditerator example:
/** * class onetimerewinditerator */ class onetimerewinditerator extends norewinditerator { private $didrewind = false; public function rewind() { if ($this->didrewind) return; $this->didrewind = true; $this->getinneriterator()->rewind(); } }
Comments
Post a Comment