Records
Prerequisites: Functions, Maps
A record (Dart 3+) bundles a few values together without defining a class. Records are immutable, can mix types, and are compared by their values.
Positional and named fields
void main() {
final point = (3, 4);
print(point);
print(point.$1);
print(point.$2);
final user = (name: 'Ada', age: 36);
print(user);
print(user.name);
final mixed = ('Ada', age: 36);
print(mixed.$1);
print(mixed.age);
print((1, 2) == (1, 2));
}
(3, 4)
3
4
(age: 36, name: Ada)
Ada
Ada
36
true
- Positional fields are read with
$1,$2, ... - Named fields are read by name. Their order doesn't matter —
(name: 'Ada', age: 36)and(age: 36, name: 'Ada')are the same record — which is why printing lists them alphabetically. - Two records with the same values are equal.
Returning several values
Records shine as return values:
(int, int) minMax(List<int> numbers) {
var low = numbers.first;
var high = numbers.first;
for (final n in numbers) {
if (n < low) low = n;
if (n > high) high = n;
}
return (low, high);
}
void main() {
final (low, high) = minMax([4, 9, 1]);
print('$low to $high');
}
1 to 9
final (low, high) = ... destructures the record into two variables
— the next lesson covers patterns like this in depth.
Record types
The type of (name: 'Ada', age: 36) is ({String name, int age}). Give
a long record type a name with a typedef:
typedef Coordinates = ({double lat, double lng});
Coordinates london() => (lat: 51.5, lng: -0.12);
void main() {
final c = london();
print('${c.lat}, ${c.lng}');
}
51.5, -0.12
Records or classes?
Records suit small, local groupings — two or three values returned from a function. For data passed widely around your app, with methods or validation, define a class.