Explication détaillée de la façon dont PHP traverse les objets

藏色散人
Libérer: 2023-04-09 18:14:01
avant
3627 Les gens l'ont consulté

Pour PHP, foreach est une syntaxe très pratique et facile à utiliser. C'est l'une des requêtes les plus courantes pour presque tous les PHP. Alors, les objets peuvent-ils être traversés par foreach ?

La réponse est oui, mais il y a une condition, c'est-à-dire que traverser un objet ne peut obtenir que ses propriétés publiques.

// 普通遍历
class A
{
    public $a1 = '1';
    public $a2 = '2';
    public $a3 = '3';

    private $a4 = '4';
    protected $a5 = '5';

    public $a6 = '6';

    public function test()
    {
        echo 'test';
    }
}
$a = new A();
foreach ($a as $k => $v) {
    echo $k, '===', $v, PHP_EOL;
}

// a1===1
// a2===2
// a3===3
// a6===6
Copier après la connexion

Peu importe qu'il s'agisse d'une méthode ou d'une variable protégée ou privée, elle ne peut pas être parcourue. Seuls les attributs publics peuvent être traversés. En fait, le Modèle d'itérateur dont nous avons parlé précédemment en parlant de modèles de conception est spécifiquement utilisé pour la traversée d'objets, et PHP a préparé les interfaces pertinentes pour nous. Il nous suffit d'implémenter cette interface. le modèle d’itérateur peut être complété. Pour un contenu spécifique, veuillez vous référer à la série précédente d'articles sur les modèles de conception : PHP Design Patterns Iterator Pattern (recommandé : "Tutoriel vidéo PHP")

// 实现迭代器接口
class B implements Iterator
{
    private $var = [];

    public function __construct($array)
    {
        if (is_array($array)) {
            $this->var = $array;
        }
    }

    public function rewind()
    {
        echo "rewinding\n";
        reset($this->var);
    }

    public function current()
    {
        $var = current($this->var);
        echo "current: $var\n";
        return $var;
    }

    public function key()
    {
        $var = key($this->var);
        echo "key: $var\n";
        return $var;
    }

    public function next()
    {
        $var = next($this->var);
        echo "next: $var\n";
        return $var;
    }

    public function valid()
    {
        $var = $this->current() !== false;
        echo "valid: {$var}\n";
        return $var;
    }
}

$b = new B([1, 2, 3, 4]);

foreach ($b as $k => $v) {
    echo $k, '===', $v, PHP_EOL;
}

// rewinding
// current: 1
// valid: 1
// current: 1
// key: 0
// 0===1
// next: 2
// current: 2
// valid: 1
// current: 2
// key: 1
// 1===2
// next: 3
// current: 3
// valid: 1
// current: 3
// key: 2
// 2===3
// next: 4
// current: 4
// valid: 1
// current: 4
// key: 3
// 3===4
// next:
// current:
// valid:
Copier après la connexion

Si l'article d'aujourd'hui ne parle que de quoi J'en ai déjà parlé. Le modèle d'itérateur est trop ennuyeux, nous devons donc apprendre une application plus intéressante. C'est pour permettre aux objets d'être manipulés comme des tableaux. Il s'agit en fait d'utiliser une interface que PHP nous a déjà préparée : ArrayAccess.

// 让类可以像数组一样操作
class C implements ArrayAccess, IteratorAggregate
{
    private $container = [];
    public function __construct()
    {
        $this->container = [
            "one" => 1,
            "two" => 2,
            "three" => 3,
        ];
    }
    public function offsetSet($offset, $value)
    {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }
    public function offsetGet($offset)
    {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }

    public function getIterator() {
        return new B($this->container);
    }
}

$c = new C();
var_dump($c);

$c['four'] = 4;
var_dump($c);

$c[] = 5;
$c[] = 6;
var_dump($c);

foreach($c as $k=>$v){
    echo $k, '===', $v, PHP_EOL;
}

// rewinding
// current: 1
// valid: 1
// current: 1
// key: one
// one===1
// next: 2
// current: 2
// valid: 1
// current: 2
// key: two
// two===2
// next: 3
// current: 3
// valid: 1
// current: 3
// key: three
// three===3
// next: 4
// current: 4
// valid: 1
// current: 4
// key: four
// four===4
// next: 5
// current: 5
// valid: 1
// current: 5
// key: 0
// 0===5
// next: 6
// current: 6
// valid: 1
// current: 6
// key: 1
// 1===6
// next: 
// current: 
// valid:
Copier après la connexion

Cette interface nous demande d'implémenter quatre méthodes :

  • offsetSet($offset, $value), définir la valeur en fonction du décalage
  • offsetExists($ offset ), déterminer si le contenu existe en fonction du décalage
  • offsetUnset($offset), supprimer le contenu en fonction du décalage
  • offsetGet($offset), obtenir le contenu en fonction du décalage

Le décalage ici est ce que nous appelons souvent l'indice. En implémentant ces quatre méthodes, nous pouvons faire fonctionner des objets comme des tableaux. Bien sûr, dans le développement quotidien, nous n’utilisons pas très souvent la possibilité de parcourir ces objets, y compris les itérateurs. Habituellement, nous convertirons directement l'objet en un obj tableau (array) pour l'étape suivante. Cependant, en Java, en particulier dans JavaBean, il existe souvent un List à l'intérieur de la classe comme son propre objet pour représenter son propre état de collection. Par comparaison, nous avons constaté que PHP peut pleinement implémenter de telles capacités et qu'il est plus pratique d'utiliser des itérateurs et l'interface ArrayAccess pour obtenir des capacités similaires. Il s’agit d’une extension de connaissances très utile. Peut-être pourrez-vous utiliser ces capacités dans votre prochain projet !

测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/201912/source/PHP%E6%80%8E%E4%B9%88%E9%81%8D%E5%8E%86%E5%AF%B9%E8%B1%A1%EF%BC%9F.ph
Copier après la connexion

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!

Étiquettes associées:
php
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal