Maison  >  Article  >  développement back-end  >  Compréhension d'IteratorIterator en php (exemple de code)

Compréhension d'IteratorIterator en php (exemple de code)

不言
不言avant
2018-10-25 16:51:512499parcourir

Le contenu de cet article concerne la compréhension d'IteratorIterator en php (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Compréhension personnelle d'IteratorIterator en PHP

Récemment, j'ai recommencé à bricoler le code source de Laravel, je l'ai presque oublié après ne pas l'avoir utilisé pendant plus d'un an. Chaque fois que je le regarde, je pars de là. J'ai beaucoup appris au collège. Si vous ne comprenez pas quelque chose, cherchez-le dans le manuel. J'ai vu la partie qui charge le fichier de configuration (config/*.php). La bibliothèque de classes spl et l'interface sont largement utilisées dans le code. Aujourd'hui, je vais parler de la classe IteratorIterator. Il y a trop peu d'informations sur Internet. Je ne suis pas très intelligent. Je l'ai fait plusieurs fois. Genius a quelques indices, et ce qui suit est ma compréhension personnelle.

Introduction à IteratorIterator

IteratorIterator est un wrapper d'itérateur, et bien sûr, c'est aussi un itérateur lui-même. Il (en supposant qu'il s'appelle Outer) doit passer dans une instance d'itérateur qui implémente le type d'interface Traversable (en supposant qu'il s'appelle Inner) lors de son instanciation. Bien sûr, vous pouvez obtenir ce paramètre d'itérateur entrant Inner via la méthode getInnerIterator d'Outer. Vous pouvez traiter l'itérateur interne Inner via les méthodes rewind(), next(), valid(), current() et key() d'Outer.

Points clés à comprendre

  1. Dans le processus de traversée d'Outer, Outer just rewind(), next(), valid(), current() et key() Tout appel transmet à l'itérateur interne Inner.

  2. Outer peut envelopper les résultats renvoyés par le transfert, mais cela n'aura aucun impact sur Inner.

Démonstration de code

<?php
namespace young;class InnerIterator implements \Iterator{
    private $dates;
    private $position;

    public function __construct($dates = [])
    {
        $this->dates    = $dates;
        $this->position = 0;
    }

    public function rewind()
    {
        echo &#39;call &#39; . __METHOD__ . &#39;<br>&#39;;
        reset($this->dates);
    }

    public function valid() 
    {
        echo &#39;call &#39; . __METHOD__ . &#39;<br>&#39;;
        if ($this->position >= count($this->dates)) {
            # code...
            return false;
        }
        return true;
    }

    public function current()
    {
        echo &#39;call &#39; . __METHOD__ . &#39;<br>&#39;;
        return $this->dates[$this->position];
    }

    public function key()
    {
        echo &#39;call &#39; . __METHOD__ . &#39;<br>&#39;;
        return $this->position;
    }

    public function next()
    {
        echo &#39;call &#39; . __METHOD__ . &#39;<br>&#39;;
        ++$this->position;
    }}class OuterIterator extends \IteratorIterator{
    function rewind()
    {
        echo __METHOD__ .  &#39;<br>&#39;;
        return parent::rewind();
    }
    
    function valid()
    {
        echo __METHOD__ . &#39;<br>&#39;;
        return parent::valid();
    }
    
    function current()
    {
        echo __METHOD__ . &#39;<br>&#39;;
        return parent::current() . &#39;_suffix&#39;;
    }
    
    function key()
    {
        echo __METHOD__ . &#39;<br>&#39;;
        return parent::key() ;
    }
    
    function next()
    {
        echo __METHOD__ . &#39;<br>&#39;;
        return parent::next() ;
    }
    
    function getInnerIterator() 
    {
        echo __METHOD__ . &#39;<br>&#39;;
        return parent::getInnerIterator();
    }}$tmpArr = array(
    &#39;2018-10-01&#39;,
    &#39;2018-10-02&#39;,
    //&#39;2018-10-03&#39;,);$inner = new InnerIterator($tmpArr);$outer = new OuterIterator($inner);foreach ($outer as $key => $value) {
    # code...
    echo $key , &#39;=>&#39; , $value . &#39;<hr>&#39;;}

Résultat d'exécution :

young\OuterIterator::rewind
call young\InnerIterator::rewind
call young\InnerIterator::valid
call young\InnerIterator::current
call young\InnerIterator::key
young\OuterIterator::valid
young\OuterIterator::current
young\OuterIterator::key
0=>2018-10-01_suffix
young\OuterIterator::next
call young\InnerIterator::next
call young\InnerIterator::valid
call young\InnerIterator::current
call young\InnerIterator::key
young\OuterIterator::valid
young\OuterIterator::current
young\OuterIterator::key
1=>2018-10-02_suffix
young\OuterIterator::next
call young\InnerIterator::next
call young\InnerIterator::valid
 young\OuterIterator::valid
 object(young\InnerIterator)#1 (2) { 
[“dates”:“young\InnerIterator”:private]=> array(2) { [0]=> 
string(10) “2018-10-01” [1]=> string(10) “2018-10-02” } 
[“position”:“young\InnerIterator”:private]=> int(2) }

Analyse des résultats

Chaque itération de Outer appellera d'abord sa propre méthode, puis la transmettra à Inner.
La valeur de retour de la méthode interne d'Outer est basée sur la valeur de retour d'Inner par rapport à la méthode.
Vous pouvez effectuer un traitement logique sur la valeur de retour de Inner dans la méthode à l'intérieur de Outer.
Lorsque la valeur Valid d'Inner renvoie false, l'Outer externe cessera également d'itérer.
La modification de la valeur de retour par la méthode dans Outer n'affectera pas Inner.
La méthode dans Outer n'exécutera pas la méthode getInnerIterator pendant le processus d'itération. Il s'agit simplement d'une interface appelante pour obtenir la méthode Inner.

Un petit ajout

Quand je parcourais les informations en ligne, je voyais de tels doutes

//假如这里还是使用了上面的两个类代码
<?php
namespace young;
class InnerIterator implements \Iterator
{
    //code 这里的代码假如和上面的一样
}
class OuterIterator extends \IteratorIterator
{
    //code 这里的代码假如和上面的一样
}
$outer->valid();           //false
$outer->current();         // _suffix  问题一
$outer->rewind();    
$outer->valid();            //true
$outer->current();         //2018-10-01_suffix
$outer->next()
$outer->rewind();
$outer->current();         //2018-10-02_suffix  问题二

Il y a deux questions ici,

  1. Première question, pourquoi current n'a aucune valeur et valide est faux

  2. Question deux, pourquoi après next et rembobinage, current est la deuxième valeur

D'après les résultats d'exécution ci-dessus, nous pouvons voir que $outer n'exécute pas de rembobinage et que $inner ne s'exécutera pas non plus, donc valid renvoie false, current est nul et _suffix est simplement épissé par lui-même.
Le deuxième problème est également très étrange. Je viens de le découvrir. Tant que le pointeur de $inner avance, il ne peut pas reculer, c'est-à-dire que l'attribut position de $inner devient 1 après le premier suivant. Même si vous rembobinez, la position est toujours 1, ce qui est un peu déroutant. . .
Donc, si vous effectuez l'opération de parcours $outer, aucune valeur ne sera sortie la deuxième fois Même si l'opération de rembobinage est effectuée la deuxième fois, cette opération sera inutile la deuxième fois~~~

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer