Frage

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

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

Wenn ich die erste Anruf $ iterIter-> rewind () , dann $ iterIter-> gültig () wahr ist. Ich bin neugierig, warum es, dass rewind () erfordert aufgerufen werden. Ich stelle mir vor, es gibt gute Gründe dafür, aber ich würde es einfach erwartet zu Iteration beginnen, was auch immer Zustand es ist innere Iterator ist in, und lassen Sie es als Option vor Beginn der Iteration zurückzuspulen.

Aufruf next () scheint auch in einem „gültigen“ Zustand zu bringen (auch wenn es in die nächsten Position vorrückt, was darauf hindeutet es zuvor an der ersten Position war).

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

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

Noch einmal, ich bin neugierig, warum ich Aufruf rewind muß (), obwohl der innere Iterator in einem gültigen Zustand zu sein.

War es hilfreich?

Lösung

Mit einem frischen Iterator die Position nicht initialisiert wird, einfach für Performance Grund können Sie Iteratoren auf anderen Iteratoren stapeln, wenn alle von ihnen während des Baus zurückspulen würde es würde einige Auswirkungen auf die Leistung sein, zusätzlich einige Iteratoren könnten ihre ändern erster Wert, nachdem der Konstruktor ausgeführt wurde - die auf Iteratoren weiter aus unbekannten

.

Iteratoren sind in der Regel durch foreach () ausgeführt, die einen Rücklauf hat () erste ...

Andere Tipps

Während die IteratorIterator Klasse Ersatz Verlängerung des gesamten Iterator-Schnittstelle implementiert und / oder einen Dekorateur eines Iterators zu erstellen Ich habe auch in dieser ausgeführt wird.

Das Dekorateur ist bereits die Lösung für das Problem, es muss nur die fehlende Funktionalität implementieren, um die Inkonsistenz zu beseitigen. Keine Notwendigkeit für ein Auto-Rücklauf:

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

Beispiel: Wenn Sie ein Iterator Objekt haben, die standardmäßig gültig ist, z.B. ArrayIterator:

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

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

Dies zeigt die Inkonsistenz der IteratorIterator Umsetzung gut, das IteratorIterator Objekt reflektiert nicht richtig den Zustand der inneren ArrayIterator. die IteratorDecorator verwendet, kann dies heilen:

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

Und wenn Sie bis hierher verfolgt haben, hier ist ein weiterer besonderer Fall, dass Sie vielleicht prüfen: Wenn Sie nicht brauchen, rewind mit dem inneren Iterator haben, können Sie einfach die NoRewindIterator verwenden, welche die Gültigkeit auch korrekt zurückgibt :

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

Genommen Johannes „kein auto-rewind“ Argumente zu berücksichtigen, das macht Sinn, da die NoRewindIterator davon aus, dass der Iterator nicht die inneren Iterators Gültigkeit korrekt zurückgespult und zeigt werden.

Aber wie der IteratorDecorator zeigt, mache ich nicht jede Art von Auto-Rücklauf sowie die Inkonsistenz zu entfernen.

Wie @johannes sagte, wird die Position nicht in den IteratorIterator initialisiert und somit ist es nicht gültig, bevor andere davon Methoden ausgeführt werden, auf sie oder wird sie mit foreach ()

verwendet

Versuchen zu tun

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

Und auch

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

Und auch beachten, dass auf einem unitiliazed IteratorIterator:

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

Beachten Sie, dass $arrayIter aus dem Code-Schnipsel zu $iterIter->getInnerIterator() identisch ist.

Hope, die etwas Licht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top