Iterable & Iterator
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 68 sur 110.
Chaque fois que vous utilisez une boucle for-in sur une List, un Set ou une autre collection, vous travaillez avec Iterable et Iterator sous le capot. Comprendre ces concepts vous permet de créer vos propres classes sur lesquelles il est possible d'itérer.
Un Iterable est n'importe quel objet capable de produire une séquence de valeurs. Il a une exigence clé : un getter iterator qui renvoie un Iterator. L'Iterator est ce qui parcourt réellement les éléments un par un :
var numbers = [1, 2, 3];
var iterator = numbers.iterator;
while (iterator.moveNext()) {
print(iterator.current); // 1, puis 2, puis 3
}La méthode moveNext() passe à l'élément suivant et retourne true s'il y en a un, ou false lorsqu'elle a terminé. La propriété current vous donne l'élément actuel.
Pour rendre votre propre classe itérable, implémentez l'interface Iterable :
class Countdown extends Iterable<int> {
final int start;
Countdown(this.start);
@override
Iterator<int> get iterator => CountdownIterator(start);
}
class CountdownIterator implements Iterator<int> {
int _current;
CountdownIterator(int start) : _current = start + 1;
@override
int get current => _current;
@override
bool moveNext() {
if (_current > 0) {
_current--;
return true;
}
return false;
}
}
void main() {
for (var n in Countdown(3)) {
print(n); // 3, 2, 1, 0
}
}Désormais, Countdown fonctionne avec les boucles for-in et toutes les méthodes Iterable telles que map, where et fold. Ce modèle est essentiel lors de la création de collections personnalisées qui s'intègrent parfaitement à l'écosystème de collections de Dart.
Défi
FacileConstruisons un générateur de plage personnalisé qui peut être parcouru à l'aide d'une boucle for-in ! Vous allez créer vos propres classes Iterable et Iterator pour générer une séquence de nombres dans une plage spécifiée.
Vous organiserez votre code en deux fichiers :
range.dart: Créez deux classes qui travaillent ensemble pour produire une séquence de nombres :- Une classe
RangeIteratorqui implémenteIterator<int>. Elle doit suivre la position actuelle et savoir quand s'arrêter. L'itérateur commence avant le premier élément, doncmoveNext()doit être appelé avant d'accéder àcurrent. - Une classe
Rangequi étendIterable<int>. Elle prend une valeurstartetenddans son constructeur et fournit un getteriteratorqui retourne unRangeIterator.
startetend. Par exemple,Range(1, 5)doit produire : 1, 2, 3, 4, 5.- Une classe
main.dart: Importez votre fichier range et démontrez votre itérable personnalisé :- Créez un
Range(1, 5)et utilisez une bouclefor-inpour imprimer chaque nombre sur sa propre ligne - Imprimez une ligne vide
- Créez un
Range(10, 13)et utilisez la méthodemappour doubler chaque valeur, puis imprimez la liste résultante
- Créez un
Parce que votre classe Range étend Iterable, elle accède automatiquement à toutes les méthodes de collection puissantes comme map, where, et fold - c'est toute la beauté de l'implémentation de l'interface Iterable !
Sortie attendue :
1
2
3
4
5
[20, 22, 24, 26]Aide-mémoire
Un Iterable est n'importe quel objet capable de produire une séquence de valeurs. Il nécessite un getter iterator qui renvoie un Iterator.
Un Iterator parcourt les éléments un par un en utilisant :
moveNext()- avance vers l'élément suivant et renvoietrues'il y en a un, oufalseune fois terminécurrent- propriété qui vous donne l'élément actuel
Utiliser un itérateur manuellement :
var numbers = [1, 2, 3];
var iterator = numbers.iterator;
while (iterator.moveNext()) {
print(iterator.current); // 1, puis 2, puis 3
}Pour rendre une classe personnalisée itérable, implémentez l'interface Iterable et créez une classe Iterator correspondante :
class Countdown extends Iterable<int> {
final int start;
Countdown(this.start);
@override
Iterator<int> get iterator => CountdownIterator(start);
}
class CountdownIterator implements Iterator<int> {
int _current;
CountdownIterator(int start) : _current = start + 1;
@override
int get current => _current;
@override
bool moveNext() {
if (_current > 0) {
_current--;
return true;
}
return false;
}
}
void main() {
for (var n in Countdown(3)) {
print(n); // 3, 2, 1, 0
}
}Les classes qui étendent Iterable fonctionnent avec les boucles for-in et accèdent automatiquement à toutes les méthodes Iterable telles que map, where et fold.
Essayez vous-même
import 'range.dart';
void main() {
// TODO : Créer un Range(1, 5) et utiliser une boucle for-in pour afficher chaque nombre
// TODO : Afficher une ligne vide
// TODO : Créer un Range(10, 13), utiliser map pour doubler chaque valeur et afficher la liste
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository