En génie logiciel, l'itérateur est un patron de conception (design pattern) comportemental.
Un itérateur est un objet qui permet de parcourir tous les éléments contenus dans un autre objet, le plus souvent un conteneur (liste, arbre, etc). Un synonyme d'itérateur est curseur, notamment dans le contexte des bases de données.
Un itérateur ressemble à un pointeur disposant essentiellement de deux primitives : accéder à l'élément pointé en cours (dans le conteneur), et se déplacer pour pointer vers l'élément suivant. En sus, il faut pouvoir créer un itérateur pointant sur le premier élément ; ainsi que déterminer à tout moment si l'itérateur a épuisé la totalité des éléments du conteneur. Diverses implémentations peuvent également offrir des comportements supplémentaires.
Le but d'un itérateur est de permettre à son utilisateur de parcourir le conteneur, c'est-à-dire d'accéder séquentiellement à tous ses éléments pour leur appliquer un traitement, tout en isolant l'utilisateur de la structure interne du conteneur, potentiellement complexe. Ainsi, le conteneur peut stocker les éléments de la façon qu'il veut, tout en permettant à l'utilisateur de le traiter comme une simple liste. Le plus souvent l'itérateur est conçu en même temps que la classe-conteneur qu'il devra parcourir, et ce sera le conteneur lui-même qui créera et distribuera les itérateurs pour accéder à ses éléments.
Dans un langage à objets comme le C#, un itérateur est un objet qui implémente l'interface IEnumerator.
interface IEnumerator { void Reset(); bool MoveNext(); object Current { get; } }
On utilise l'iterateur pour accéder aux valeurs disponibles.
IterateurTypique iterateur = new IterateurTypique (); iterateur.Reset(); // optionnel: cet appel peut ne pas être effectué. while(iterateur.MoveNext()){ Console.WriteLine(iterateur.Current); }
Une des nombreuses implémentations de l'objet possibles peut ressembler à celle-ci.
class IterateurTypique : IEnumerator { private string[] _chainesAParcourir = new string[] { "TF1", "France2", "FR3", "Canal+" }; private int _positionCourante = -1; public void Reset() { _positionCourante = -1; } public bool MoveNext() { if( _positionCourante + 1 >= _chainesAParcourir.Length ) return false; _positionCourante +=1; return true; } public object Current { get { return _chainesAParcourir[_positionCourante]; } } }
L'interface IEnumerable de C# permet le passage à un itérateur implicite.
interface IEnumerable { IEnumerator GetEnumerator(); }
les tableaux, listes ou dictionnaires de C# sont des types dérivés de IEnumerable et possèdent une méthode GetEnumerator() qui appelle l'itérateur explicite.
l'instruction foreach du C# appelle cette méthode GetEnumerator() et procède à une itération explicite tout en cachant les détails de l'implémentation.
if(Television is IEnumerable) { foreach(object chaine in Television) { Console.WriteLine(chaine); } }
Dans les langages procéduraux on utilise souvent un index dans une simple boucle, pour accéder séquentiellement à tous les éléments, notamment d'un tableau. Quoique cette approche reste possible en programmation objet pour certains conteneurs, l'utilisation des itérateurs a certains avantages:
La possibilité pour un conteneur de se voir modifié pendant une itération s'est imposée comme nécessaire dans la programmation objet moderne, où les relations entre objets et l'effet de certaines opérations peut devenir un casse-tête. En utilisant un tel itérateur « robuste », ces désagréments nous sont épargnés.