2
$arrayIter = new ArrayIterator( array(1, 2) );
$iterIter = new IteratorIterator($arrayIter);

var_dump($iterIter->valid()); //false
var_dump($arrayIter->valid()); //true

最初に$iterIter->rewind()を呼び出すと、$iterIter->valid()は true になります。rewind() を呼び出す必要がある理由が気になります。それには正当な理由があると思いますが、内部イテレータの状態が何であれ、単純に反復を開始し、反復を開始する前に巻き戻すオプションとしてそのままにしておくことを期待していました。

next() を呼び出すと、それが「有効な」状態になるようにも見えます (ただし、以前は最初の位置にあったことを示唆して、次の位置に進みます)。

$arrayIter = new ArrayIterator(array(1,2));
$iterIter = new IteratorIterator($arrayIter);

$iterIter->next();
var_dump($iterIter->valid()); 

繰り返しますが、内部イテレータが有効な状態にあるにもかかわらず、rewind() を呼び出す必要があるのはなぜでしょうか。

4

3 に答える 3

6

新しいイテレータでは位置が初期化されません。単純にパフォーマンス上の理由から、イテレータを他のイテレータの上に積み重ねることができます。構築中にすべてのイテレータが巻き戻されると、パフォーマンスに影響が出る可能性があります。コンストラクターが実行されました-これは、さらに先のイテレーターには不明です。

イテレータは通常、最初に rewind() を実行する foreach() によって実行されます ...

于 2010-03-16T23:38:35.660 に答える
3

クラスを拡張して、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)

Johannes の "no auto-rewind" 引数を考慮に入れると、これは理にかなってNoRewindIteratorいます。なぜなら、 は反復子が巻き戻されるべきではなく、内側の反復子の有効性を正しく示しているからです。

しかし、IteratorDecoratorショーのように、矛盾を取り除くために自動巻き戻しも行いません。

于 2012-02-27T20:13:39.623 に答える
1

@johannesが言ったように、位置はで初期化されてい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

また、ユニティライズされた IteratorIterator では次の点にも注意してください。

$iterIter->next(); // 2
var_dump( $iterIter->current()) ; // 2 (from NULL to 2)
var_dump( $iterIter->getInnerIterator()->current() );  // 2

$arrayIterコード スニペットからは と同じであることに注意してください$iterIter->getInnerIterator()

いくつかの光を当てることを願っています。

于 2010-03-16T23:39:41.080 に答える