Pregunta

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

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

Si la primera llamada $ iterIter-> rebobinado () , entonces $ iterIter-> válida () es cierto. Tengo curiosidad por lo que requiere que el rebobinado () se llama. Me imagino que hay una buena razón para ello, pero me hubiera esperado que simplemente inicia la iteración en el estado en que está iterador interno está en, y dejarlo como una opción para rebobinar antes de comenzar la iteración.

llamar a next () también parece ponerlo en un estado "válido" (aunque se avanza a la siguiente posición, sugiriendo que era previamente en la primera posición).

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

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

Una vez más, tengo curiosidad por lo que necesito llamar rewind (), a pesar del iterador interno está en un estado válido.

¿Fue útil?

Solución

Con un iterador fresca la posición no se ha inicializado, simplemente por motivos de rendimiento, se puede apilar iteradores encima de otras iteradores, si todos ellos se rebobinar durante la construcción que habría algún impacto en el rendimiento, además, algunos iteradores podrían cambiar su primer valor después de que se ejecuta el constructor -. que es desconocido para iteradores más lejos

Los iteradores se ejecutan normalmente mediante foreach () que hace un retroceso () primero ...

Otros consejos

Mientras se extiende la clase IteratorIterator de sobra la implementación de toda la interfaz iterador y / o para crear un decorador de un iterador que he estado corriendo en esto también.

Eso decorador ya es la solución al problema, que sólo necesita para implementar la funcionalidad que falta para eliminar la incompatibilidad. No hay necesidad de un auto-rebobinado:

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

Ejemplo: si se tiene un objeto Iterator que es válida de forma predeterminada, por ejemplo, ArrayIterator:

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

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

Esto demuestra la inconsistencia de la aplicación IteratorIterator así, el objeto IteratorIterator no refleja adecuadamente el estado del ArrayIterator interior. Utilizando el IteratorDecorator puede curar esto:

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

Y si usted ha seguido hasta aquí, aquí es otro caso especial es posible que desee tener en cuenta: Si no necesita tener rewind con el iterador interno, que sólo puede utilizar el NoRewindIterator que devuelve la validez correcta, así :

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

Tomados Johannes "no auto-rebobinado" argumentos en cuenta, esto tiene sentido, ya que el NoRewindIterator espera que el iterador no debe ser rebobinado y demuestra la validez del iterador interno correctamente.

Sin embargo, como muestra el IteratorDecorator, no hago ningún tipo de auto-rebobinado así a eliminar la incompatibilidad.

Como @johannes dijo, la posición no se inicializa en el IteratorIterator y por lo tanto no es válido antes de cualquier otra de la misma de métodos se ejecutan en él o se utiliza con foreach ()

Trate de hacer

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

Y también

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

Y también en cuenta que en una IteratorIterator unitiliazed:

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

Tenga en cuenta que $arrayIter desde el fragmento de código es idéntico al $iterIter->getInnerIterator().

La esperanza de que arrojar algo de luz.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top