なぜ私はIteratorIteratorを巻き戻す必要があります
質問
$arrayIter = new ArrayIterator( array(1, 2) );
$iterIter = new IteratorIterator($arrayIter);
var_dump($iterIter->valid()); //false
var_dump($arrayIter->valid()); //true
もし私の最初の呼び出しの$ iterIter->巻き戻し()の場合、の$ iterIter->有効()のは本当です。それは巻き戻し()が呼び出されている必要があり、なぜ私は興味があります。私はそれのための十分な理由があると想像しますが、私は単にそれが内部イテレータの中で何でも状態で反復開始し、反復を開始する前に巻き戻すためのオプションとして、それを残すためにそれを期待しているだろう。
を呼び出す()も(それが第1の位置に以前だった示唆、それは次の位置に進みますが)「有効」状態に入れているようだ。次の
$arrayIter = new ArrayIterator(array(1,2));
$iterIter = new IteratorIterator($arrayIter);
$iterIter->next();
var_dump($iterIter->valid());
私は内部イテレータが有効な状態であるにも関わらず、巻き戻し()を呼び出す必要があり、なぜ繰り返しますが、私は興味があります。
解決
の位置が初期化されていない新鮮なイテレータでは、単にパフォーマンス上の理由のために、あなたは、さらにいくつかのイテレータは自分を変えるかもしれない、それらのすべてが建設中に巻き戻すかどういくつかのパフォーマンスへの影響があるだろう、他のイテレータの上にイテレータを積み重ねることができますコンストラクタが実行された後の最初の値 - イテレータに知られていないさらにアウト
イテレータは、通常、巻き戻し()はforeachの()によって実行された第1 ...
他のヒント
全体Iteratorインターフェイスを実装する余裕がおよび/または私もこのに実行してきたイテレータのデコレータを作成するために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
が示すように、私は矛盾を削除するだけでなく、自動巻き戻しのいずれかの種類を行いません。
のように、位置がIteratorIterator
に初期化されていませんし、それの方法のいずれかの他は、それ上で実行されているか、foreachのに使用される前に、それが有効ではありませんのでれる()
タグを行うようにしてください
var_dump( $iterIter->current() ); // NULL
var_dump( $iterIter->getInnerIterator()->current() ); // 1
も
$iterIter->rewind();
var_dump( $iterIter->current() ); // 1
var_dump( $iterIter->getInnerIterator()->->current() ); // 1
そしてまたunitiliazed IteratorIterator上の点に注意します:
$iterIter->next(); // 2
var_dump( $iterIter->current()) ; // 2 (from NULL to 2)
var_dump( $iterIter->getInnerIterator()->current() ); // 2
あなたのコードスニペットからその$arrayIter
が$iterIter->getInnerIterator()
と同じであることに注意してください。
いくつかの光を当てる希望ます。