Iterable & Iterator
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 68 of 110.
Every time you use a for-in loop on a List, Set, or other collection, you're working with Iterable and Iterator under the hood. Understanding these concepts lets you create your own classes that can be looped over.
An Iterable is any object that can produce a sequence of values. It has one key requirement: an iterator getter that returns an Iterator. The Iterator is what actually moves through the elements one by one:
var numbers = [1, 2, 3];
var iterator = numbers.iterator;
while (iterator.moveNext()) {
print(iterator.current); // 1, then 2, then 3
}The moveNext() method advances to the next element and returns true if there is one, or false when finished. The current property gives you the current element.
To make your own class iterable, implement the Iterable interface:
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
}
}Now Countdown works with for-in loops and all Iterable methods like map, where, and fold. This pattern is essential when building custom collections that integrate seamlessly with Dart's collection ecosystem.
Challenge
EasyLet's build a custom range generator that can be iterated over using a for-in loop! You'll create your own Iterable and Iterator classes to generate a sequence of numbers within a specified range.
You'll organize your code into two files:
range.dart: Create two classes that work together to produce a sequence of numbers:- A
RangeIteratorclass that implementsIterator<int>. It should track the current position and know when to stop. The iterator starts before the first element, somoveNext()must be called before accessingcurrent. - A
Rangeclass that extendsIterable<int>. It takes astartandendvalue in its constructor and provides aniteratorgetter that returns aRangeIterator.
startandend. For example,Range(1, 5)should produce: 1, 2, 3, 4, 5.- A
main.dart: Import your range file and demonstrate your custom iterable:- Create a
Range(1, 5)and use afor-inloop to print each number on its own line - Print an empty line
- Create a
Range(10, 13)and use themapmethod to double each value, then print the resulting list
- Create a
Because your Range class extends Iterable, it automatically gains access to all the powerful collection methods like map, where, and fold - that's the beauty of implementing the Iterable interface!
Expected output:
1
2
3
4
5
[20, 22, 24, 26]Cheat sheet
An Iterable is any object that can produce a sequence of values. It requires an iterator getter that returns an Iterator.
An Iterator moves through elements one by one using:
moveNext()- advances to the next element and returnstrueif there is one, orfalsewhen finishedcurrent- property that gives you the current element
Using an iterator manually:
var numbers = [1, 2, 3];
var iterator = numbers.iterator;
while (iterator.moveNext()) {
print(iterator.current); // 1, then 2, then 3
}To make a custom class iterable, implement the Iterable interface and create a corresponding Iterator class:
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
}
}Classes that extend Iterable work with for-in loops and automatically gain access to all Iterable methods like map, where, and fold.
Try it yourself
import 'range.dart';
void main() {
// TODO: Create a Range(1, 5) and use a for-in loop to print each number
// TODO: Print an empty line
// TODO: Create a Range(10, 13), use map to double each value, and print the list
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesLibraries & ImportsIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsInstance VariablesConstructor BasicsRecap - Simple Calculator4Null Safety
Intro to Null SafetyNullable vs Non-NullableThe ? and ! OperatorsLate Keyword & Null SafetyNull-Aware OperatorsNull Safety in ClassesRecap - User Profile System7Abstract Classes & Interfaces
Abstract ClassesAbstract MethodsInterfaces in DartImplicit InterfacesImplementing vs ExtendingMultiple InterfacesRecap - Shape Calculator10Collections & Generics
List, Set, Map OverviewType-Safe CollectionsGeneric ClassesGeneric MethodsGeneric ConstraintsIterable & IteratorRecap - Generic Storage13Advanced OOP Concepts
Composition vs InheritanceExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums with Methods16Project: Library Management
Project OverviewBook and User Classes2Constructors in Dart
Default ConstructorNamed ConstructorsInitializer ListsConstant ConstructorsFactory ConstructorsRedirecting ConstructorsRecap - Shape Builder5Encapsulation
Public vs Private MembersThe _ Prefix ConventionLibrary-Level PrivacyGetters & Setters DepthInformation HidingRecap - Student Records8Mixins
Introduction to MixinsCreating MixinsUsing Multiple Mixinson Keyword in MixinsMixin vs InheritanceMixin vs InterfaceRecap - Animal System11Special Methods
toString() OverridehashCode & == OverrideComparable Interfacecall() MethodnoSuchMethod OverrideRecap - Custom Collection14Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern3Class Properties
Instance vs Static MembersFinal & Const FieldsLate VariablesStatic Methods & FieldsGetters and SettersRecap - Bank Account Manager6Inheritance
Basic InheritanceThe super KeywordMethod OverridingThe @override AnnotationThe final Class KeywordConstructors & InheritanceRecap - Employee Hierarchy9Polymorphism
Polymorphism BasicsPolymorphism via InterfacesRuntime Type CheckingThe is & as OperatorsCovariant KeywordRecap - Payment Processor