Domanda

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

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

Se io prima chiamata $ iterIter-> rewind () , quindi $ iterIter-> valido () è vero. Sono curioso di sapere perchè si richiede che rewind () essere chiamato. Immagino che ci sia una buona ragione per questo, ma mi sarei aspettato di esso per avviare semplicemente l'iterazione in qualsiasi stato è iteratore interna è in, e lasciarlo come opzione per riavvolgere prima di iniziare iterazione.

chiamando next () sembra anche di metterlo in uno stato "valido" (anche se avanza alla posizione successiva, suggerendo che in precedenza era al primo posto).

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

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

Anche in questo caso, io sono curioso di sapere perchè ho bisogno di chiamare rewind (), nonostante l'iteratore interno essendo in uno stato valido.

È stato utile?

Soluzione

Con un iteratore fresca la posizione non è inizializzato, semplicemente per ragioni di prestazioni, è possibile impilare iteratori in cima ad altre iteratori, se tutti loro sarebbe riavvolgere durante la costruzione ci sarebbe qualche impatto sulle prestazioni, in aggiunta alcuni iteratori potrebbero cambiare la loro primo valore dopo il costruttore è stato eseguito -. che è sconosciuto ai più lontano iteratori

Gli iteratori vengono di solito effettuate da foreach (), che fa un rewind () prima ...

Altri suggerimenti

Mentre si estende la classe IteratorIterator di risparmiare attuare l'intera interfaccia iteratore e / o per creare un decoratore di un iteratore Ho corso in questo.

Questo decoratore è già la soluzione al problema, ha solo bisogno di implementare la funzionalità mancante per rimuovere l'inconsistenza. Non c'è bisogno di un auto-riavvolgimento:

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

Esempio: Se si dispone di un oggetto Iterator che è valida per impostazione predefinita, ad esempio, ArrayIterator:

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

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

Questo dimostra l'inconsistenza della realizzazione IteratorIterator bene, l'oggetto IteratorIterator non riflette correttamente lo stato del ArrayIterator interiore. Utilizzando il IteratorDecorator può guarire questo:

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

E se avete seguito fino a qui, qui è un altro caso particolare si potrebbe prendere in considerazione: se non c'è bisogno di avere rewind con l'iteratore interno, si può semplicemente utilizzare il NoRewindIterator che restituisce la validità corretta così :

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

Preso Johannes "no auto-rewind" argomenti in considerazione, questo ha un senso, come il NoRewindIterator si aspetta che l'iteratore non dovrebbe essere riavvolto e mostra la validità del iteratore interno correttamente.

Ma come mostra IteratorDecorator, non faccio nessun tipo di auto-riavvolgimento e per rimuovere l'inconsistenza.

Come @johannes detto, la posizione non è inizializzato nel IteratorIterator e quindi non è valido prima di ogni altro di esso è metodi gestiscono su di esso o si utilizza con foreach ()

Prova a fare

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

E anche

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

E anche notare che su un IteratorIterator unitiliazed:

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

Si noti che $arrayIter dal frammento di codice è identico a $iterIter->getInnerIterator().

La speranza che a far luce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top