Расширяя класс IteratorIterator
, чтобы сэкономить реализацию всего интерфейса итератора и / или создать декоратор итератора, с которым я тоже столкнулся.
Тот факт, что декоратор уже является решением проблемы, ему нужно только реализовать недостающие функциональные возможности для устранения несоответствия. Нет необходимости в автоперемотке:
class IteratorDecorator extends IteratorIterator
{
public function valid()
{
return $this->getInnerIterator()->valid();
}
}
Пример: если у вас есть объект Iterator
, который является допустимым по умолчанию, например, ArrayIterator
$it = new ArrayIterator(array(1));
var_dump($it->valid()); # bool(true)
$itit = new IteratorIterator($it);
var_dump($itit->valid()); # bool(false)
Это хорошо показывает несоответствие реализации IteratorIterator
, объект IteratorIterator
неправильно отражает внутреннее состояние ArrayIterator
. Использование IteratorDecorator
может излечить это:
$decor = new IteratorDecorator($it);
var_dump($decor->valid()); # bool(true)
И если вы следили до этого момента, вот еще один особый случай, который вы могли бы рассмотреть: если вам не нужно иметь rewind
с внутренним итератором, вы можете просто использовать NoRewindIterator
, который возвращает срок действия также корректен:
$noretit = new NoRewindIterator($it);
var_dump($noretit->valid()); # bool(true)
Приняв во внимание аргументы Йоханнеса об отсутствии автоматической перемотки, это имеет смысл, так как NoRewindIterator
ожидает, что итератор не должен быть перезаписан, и правильно показывает действительность внутреннего итератора.
Но, как показывает IteratorDecorator
, я не делаю никакой автоматической перемотки, чтобы устранить несоответствие.