Iterator în Dart

Obiectul care parcurge un Iterable pas cu pas; for-in îl folosește în spate prin getter-ul iterator.

Sintaxă
abstract interface class Iterator<E>

Iterator<E> get iterator   // în Iterable<E>

Ce face Iterator

Orice Iterable are getter-ul iterator, care returnează un Iterator nou, poziționat înaintea primului element. Bucla for (final x in colectie) cere acest iterator și cheamă moveNext() și current până la final.

Rareori folosești un iterator direct. Îți trebuie când scrii propria clasă Iterable: extinzi Iterable<E>, implementezi doar Iterator<E> get iterator și primești gratuit map, where, toList și restul metodelor.

Ce returnează

iterator returnează un Iterator<E> nou la fiecare apel.

Exemple

Exemplul 1: Ce face for-in în spate

void main() {
  final orase = ['Iași', 'Cluj', 'Timișoara'];
  final it = orase.iterator;
  while (it.moveNext()) {
    print('Oraș: ${it.current}');
  }
}

Rezultat

Oraș: Iași
Oraș: Cluj
Oraș: Timișoara

Exemplul 2: Propria clasă Iterable

Clasa Interval definește doar iterator; where, toList și length vin de la Iterable.

class Interval extends Iterable<int> {
  final int start, sfarsit;
  Interval(this.start, this.sfarsit);

  @override
  Iterator<int> get iterator => _IteratorInterval(start, sfarsit);
}

class _IteratorInterval implements Iterator<int> {
  final int _sfarsit;
  int _curent;
  _IteratorInterval(int start, this._sfarsit) : _curent = start - 1;

  @override
  int get current => _curent;

  @override
  bool moveNext() {
    if (_curent >= _sfarsit) return false;
    _curent++;
    return true;
  }
}

void main() {
  final zile = Interval(1, 7);
  print(zile.toList());
  print(zile.where((z) => z.isEven).toList());
  print('Lungime: ${zile.length}');
}

Rezultat

[1, 2, 3, 4, 5, 6, 7]
[2, 4, 6]
Lungime: 7

Greșeli frecvente

  • Citești current înainte de primul moveNext(). Iteratorul nu este încă pe niciun element.
  • Salvezi un iterator și îl folosești a doua oară după ce a ajuns la final. Un iterator merge doar înainte; cere unul nou cu colectie.iterator.

Comenzi înrudite

  • Iterator.moveNext: moveNext trece la elementul următor și spune dacă există; current dă elementul pe care stă iteratorul.
  • Iterable: Tipul de bază pentru orice colecție care poate fi parcursă element cu element: List, Set, cheile unui Map.
  • sync* și yield: O funcție sync* este un generator: produce elementele unui Iterable unul câte unul, cu yield, doar când sunt cerute.
  • for-in: Parcurge pe rând elementele unei liste, unui set sau oricărui Iterable, fără indice.