Neden IteratorIterator sarmak gerekir

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

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

Ben ilk çağrı $iterIter->rewind(), sonra da $iterIter->valid() doğruysa. O geri sarma () denilen gerektirir neden merak ediyorum. Ben bunun için iyi bir neden var hayal, ama ben sadece o iç yineleyici olduğu ne olursa olsun devlet de yineleme başlayacak ve yineleme başlamadan önce sarmak için bir seçenek olarak bırakmak umuyordum.

(o ilk pozisyonda önce olduğu düşündüren, bir sonraki pozisyona ilerler rağmen) next () çağırarak aynı zamanda bir "geçerli" bir devlet koymak gibi görünüyor.

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

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

Ben geri sarma (aramak için neden ihtiyaç Yine, geçerli bir devlet olmanın iç yineleyici rağmen) merak ediyorum.

3 Cevap

Hepsi yapımı sırasında geri sarmak olsaydı pozisyonu basitçe performans nedenle, başlatılmadı taze bir yineleyici ile, diğer Yineleyicilerde üstüne yineleyicileri yığını olabilir, ayrıca bazı Yineleyicilerde sonra ilk değerini değişebilir, bazı performans etkisi olacağını yapıcı idam edildi - daha fazla dışarı Yineleyicilerin bilinmeyen hangi.

Yineleyicilerde genellikle önce bir geri sarma () yapar) foreach (tarafından yürütülür ...

Bütün yineleyici arabirimi uygulayan yedek ve / veya ben de bu içine çalışan oldum bir yineleyici bir dekoratör oluşturmak için IteratorIterator sınıf uzatırken.

Bu dekoratör zaten sorunun çözümü, sadece tutarsızlığı kaldırmak için eksik işlevselliğini uygulamak gerekiyor. Otomatik geri sarma için gerek yok:

class IteratorDecorator extends IteratorIterator
{
    public function valid()
    {
        return $this->getInnerIterator()->valid();
    }
}

Örnek: Eğer varsayılan olarak geçerli olan bir Iterator nesne varsa, örneğin ArrayIterator,

$it = new ArrayIterator(array(1));
var_dump($it->valid());             # bool(true)

$itit = new IteratorIterator($it);
var_dump($itit->valid());           # bool(false)

Bu iyi, IteratorIterator nesne düzgün iç ArrayIterator 'nin durumunu yansıtmamaktadır IteratorIterator uygulama tutarsızlık gösterir. Kullanarak IteratorDecorator Bu iyileşmek:

$decor = new IteratorDecorator($it);
var_dump($decor->valid());          # bool(true)

Buraya kadar takip Ve eğer, burada düşünebilirsiniz başka bir özel durum: Eğer iç yineleyici ile rewind olması gerekmez, sadece kullanabilirsiniz {[(1) }] de hangi doğru geçerliliğini verir:

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

NoRewindIterator yineleyici rewinded gerektiğini bekler ve doğru iç yineleyici geçerliliğini gösterir olarak dikkate Johannes "no auto-geri sarma" argümanlar ele alındığında, bu, mantıklı.

Ama IteratorDecorator gösterdiği gibi, ben her türlü yapmazsanız tutarsızlık kaldırmak için de otomatik geri sarma.

@ Johannes Dediğim gibi, pozisyon IteratorIterator olarak başlatılmış değildir ve yöntemlerini başka üzerinde çalıştırılan veya foreach ile kullanılmadan önce dolayısıyla (geçerli değildir)

Yapmaya çalışın

var_dump( $iterIter->current() ); // NULL
var_dump( $iterIter->getInnerIterator()->current() ); // 1

Ve ayrıca

$iterIter->rewind();
var_dump( $iterIter->current() ); // 1
var_dump( $iterIter->getInnerIterator()->->current() );  // 1

Ve ayrıca note that on an unitiliazed IteratorIterator:

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

$arrayIter kod parçacığını gelen $iterIter->getInnerIterator() ile aynı olduğunu unutmayın.

Bazı ışık tutacak umuyoruz.