Menu
Coddy logo textTech

Iterable e Iterator

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy. Lección 68 de 110.

Cada vez que usas un bucle for-in en una List, un Set u otra colección, estás trabajando con Iterable y Iterator internamente. Comprender estos conceptos te permite crear tus propias clases que se pueden recorrer en un bucle.

Un Iterable es cualquier objeto que puede producir una secuencia de valores. Tiene un requisito clave: un getter iterator que devuelve un Iterator. El Iterator es lo que realmente avanza por los elementos uno a uno:

var numbers = [1, 2, 3];
var iterator = numbers.iterator;

while (iterator.moveNext()) {
  print(iterator.current);  // 1, luego 2, luego 3
}

El método moveNext() avanza al siguiente elemento y devuelve true si hay uno, o false cuando termina. La propiedad current le proporciona el elemento actual.

Para hacer que tu propia clase sea iterable, implementa la interfaz 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
  }
}

Ahora Countdown funciona con bucles for-in y todos los métodos de Iterable como map, where y fold. Este patrón es esencial al crear colecciones personalizadas que se integran perfectamente con el ecosistema de colecciones de Dart.

challenge icon

Desafío

Fácil

¡Construyamos un generador de rangos personalizado que se pueda recorrer mediante un bucle for-in! Crearás tus propias clases Iterable e Iterator para generar una secuencia de números dentro de un rango especificado.

Organizarás tu código en dos archivos:

  • range.dart: Crea dos clases que trabajen juntas para producir una secuencia de números:
    • Una clase RangeIterator que implemente Iterator<int>. Debe realizar un seguimiento de la posición actual y saber cuándo detenerse. El iterador comienza antes del primer elemento, por lo que se debe llamar a moveNext() antes de acceder a current.
    • Una clase Range que extienda Iterable<int>. Recibe un valor start y un valor end en su constructor y proporciona un getter iterator que devuelve un RangeIterator.
    El rango debe incluir tanto start como end. Por ejemplo, Range(1, 5) debe producir: 1, 2, 3, 4, 5.
  • main.dart: Importa tu archivo de rango y demuestra tu iterable personalizado:
    • Crea un Range(1, 5) y usa un bucle for-in para imprimir cada número en su propia línea
    • Imprime una línea vacía
    • Crea un Range(10, 13) y usa el método map para duplicar cada valor; después, imprime la lista resultante

Como tu clase Range extiende Iterable, obtiene automáticamente acceso a todos los potentes métodos de colecciones, como map, where y fold; ¡esa es la ventaja de implementar la interfaz Iterable!

Salida esperada:

1
2
3
4
5

[20, 22, 24, 26]

Pruébalo tú mismo

import 'range.dart';

void main() {
  // TODO: Crear un Range(1, 5) y usar un bucle for-in para imprimir cada número
  
  
  // TODO: Imprimir una línea vacía
  
  
  // TODO: Crear un Range(10, 13), usar map para duplicar cada valor y imprimir la lista
  
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Dart online