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()为真。我很好奇为什么它需要调用 rewind() 。我想这是有充分理由的,但我原以为它会在内部迭代器所处的任何状态下简单地开始迭代,并将其作为在开始迭代之前回退的选项。

调用 next() 似乎也将其置于“有效”状态(尽管它前进到下一个位置,表明它之前位于第一个位置)。

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

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

同样,我很好奇为什么我需要调用 rewind(),尽管内部迭代器处于有效状态。

4

3 回答 3

6

使用新的迭代器,位置不会被初始化,只是出于性能原因,您可以将迭代器堆叠在其他迭代器之上,如果它们在构造过程中全部倒退,则会对性能产生一些影响,另外一些迭代器可能会在之后更改它们的第一个值构造函数被执行——这对于更远的迭代器来说是未知的。

迭代器通常由 foreach() 执行,它首先执行 rewind() ...

于 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使用内部迭代器,您也可以使用NoRewindIteratorwhich 返回正确的有效性:

$noretit = new NoRewindIterator($it);
var_dump($noretit->valid());        # bool(true)

考虑到 Johannes “没有自动倒带”的论点,这是有道理的,因为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 回答