« Patrons de conception/Itérateur » : différence entre les versions

Contenu supprimé Contenu ajouté
m 57 versions depuis w:Itérateur (patron de conception) : Patrons de conception/Itérateur
+
Ligne 1 :
<noinclude>{{Patrons de conception}}
En [[génie logiciel]], l''''itérateur''' est un [[patron de conception]] ''(design pattern)'' [[patron de conception#Comportement|comportemental]].
{{Patron de conception|Itérateur|Iterator|Parcourir un ensemble d'objets à l'aide d'un objet de contexte}}</noinclude>
 
L''''itérateur''' est un [[../|patron de conception]] [[../Patrons de comportement|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 (informatique)|arbre]], etc.). Un synonyme d'itérateur est [[curseur]], notamment dans le contexte des [[base de données|bases de données]].
 
== Description ==
 
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.
 
== Différences avec l'indexation ==
 
Dans les [[langage procédural|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érateur (patron de conception)|itérateur]]sitérateurs a certains avantages :
* Un simple compteur dans une boucle n'est pas adapté à toutes les structures de données, en particulier :
** celles qui n'ont pas de méthode d'accès à un élément quelconque,
** celles dont l'accès à un élément quelconque est très lent (c'est le cas des [[liste chaînée|listes chaînées]] et des [[arbre (informatique)|arbre]]sarbres).
* Les itérateurs fournissent un moyen cohérent d'''itérer'' sur toutes sortes de structures de données, rendant ainsi le code client plus lisible, réutilisable, et robuste même en cas de changement dans l'organisation de la structure de données.
* Une structure arborescente peut fournir différents types d'itérateurs retournant les nœuds de l'arbre dans un ordre différent : parcours récursif, parcours par niveau, ...
* Un itérateur peut implanter des restrictions additionnelles sur l'accès aux éléments, par exemple pour empêcher qu'un élément soit « sauté », ou qu'un même élément soit visité deux fois.
* Un itérateur peut ''dans certains cas'' permettre que le conteneur soit modifié, sans être invalidé pour autant. Par exemple, après qu'un itérateur s'est positionné derrière le premier élément, il est possible d'insérer d'autres éléments au début du conteneur avec des résultats prévisibles. Avec un index on aurait plus de problèmes, parce que la valeur de l'index devrait elle aussi être modifiée en conséquence.<br/>
'''Important :''' il est indispensable de bien consulter la documentation d'un itérateur pour savoir dans quels cas il est invalidé ou non.
 
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.
 
== Utilisation d'un itérateur explicite ==
Ligne 26 ⟶ 37 :
 
<source lang=csharp>
interface IEnumerator
{
void Reset();
bool MoveNext();
Ligne 33 ⟶ 45 :
</source>
 
On utilise l'iterateuritérateur pour accéder aux valeurs disponibles.
 
<source lang=csharp>
IterateurTypique iterateur = new IterateurTypique ();
 
iterateur.Reset(); // optionnel : cet appel peut ne pas être effectué.
while(iterateur.MoveNext())
{
Console.WriteLine(iterateur.Current);
}
}
</source>
 
Ligne 47 ⟶ 60 :
 
<source lang=csharp>
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;
{
if( _positionCourante + 1 >= _chainesAParcourir.Length ) return false;
 
_positionCourante +=1;
return true;
}
 
public object Current { get { return _chainesAParcourir[_positionCourante]; } }
public object Current
{
public object Current { get { return _chainesAParcourir[_positionCourante]; } }
}
}
</source>
Ligne 66 ⟶ 86 :
 
<source lang=csharp>
interface IEnumerable
{
IEnumerator GetEnumerator();
}
Ligne 76 ⟶ 97 :
 
<source lang=csharp>
if(Television is IEnumerable)
{
foreach(object chaine in Television) {
}{
Console.WriteLine(chaine);
}
Ligne 85 ⟶ 108 :
== Itérateurs implicites ==
 
Des langages à objets comme [[PerlProgrammation (langage)Perl|Perl]] et [[PythonProgrammation (langage)Python|Python]] fournissent un moyen « interne » d'itérer sur les éléments d'un conteneur sans introduire explicitement un itérateur.
Cela est souvent implantéimplémenté par une structure de contrôle ''for-each'', comme dans les exemples suivants :
 
<source lang="tcl">
# Tcl: itérateur implicite
foreach val $list {
puts stdout $val
}
}
</source>
 
<source lang="perl">
# Perl: itérateur implicite
foreach $val (@list) {
print "$val\n";
}
}
</source>
 
<source lang="python">
# Python, itérateur implicite
for Value in List:
print Value
</source>
 
<source lang="php">
// PHP, itérateur implicite
foreach ($list as $value)
print $value;
</source>
 
<source lang="java">
// Java, J2SE 5.0, itérateur implicite
for (Value v : list)
System.out.print(v);
</source>
 
<source lang="csharp">
// C#, itérateur implicite
foreach (object obj in list)
Console.WriteLine(obj );
 
// C#, itérateur explicite avec un yield
foreach (object obj in IndicesPairs() )
Console.WriteLine(obj);
 
// ou IndicesPairs() est une méthode
IEnumerable IndicesPairs() {
for(int i=0; i<tableau.Length; i++)
if(i%2==0)
yield return tableau[i];
}
 
// ou IndicesPairs() est une méthode
IEnumerable IndicesPairs() {
{
for(int i=0; i<tableau.Length; i++)
if(i%2==0)
yield return tableau[i];
}
</source>
 
<source lang="ruby">
# Ruby, itérateur de bloc, (yield)
list.each do |value|
puts value
end
 
# ou each est une méthode de Array tel que :
def each
for i in 0...size
for i in yield(self[i])0...size
endyield(self[i])
end
end
</source>
 
Ligne 154 ⟶ 178 :
 
<source lang="javascript">
// Javascript, itérateur implicite
for(nom in Object)
{
var valeur = Object[nom];
alert(Value+" = "+valeur ]);
}
}
</source>
 
Le langage [[Progrmmation C++|C++]] dispose également de la fonction template <code>std::for_each()</code> qui permet des itérations implicites similaires, mais requiert toujours de fournir des objets itérateurs en paramètres d'entrée.
 
'''''Remarque''' : le Ruby (ainsi que le [[C_sharp|C#]] à partir de sa version 2.0), offre via yield un outil spécifique pour construire des itérateurs. ''
 
{{Portail informatique}}
 
[[Catégorie:Patron de conception]]
 
'''''Remarque''' : le Ruby (ainsi que le [[C_sharpProgrammation C sharp|C#]] à partir de sa version 2.0), offre via yield un outil spécifique pour construire des itérateurs. ''
[[da:Enumerator]]
[[de:Iterator]]
[[en:Iterator]]
[[es:Iterador (patrón de diseño)]]
[[it:Iterator pattern]]
[[ja:イテレータ]]
[[nl:Iterator]]
[[pl:Iterator]]
[[pt:Iterator]]
[[ru:Итератор]]
[[sv:Iterator]]
[[zh:迭代器]]