Lección 10 · 10 de 20
Records y desestructuración · Dart
Devuelva varios valores sin crear clases con los records de Dart 3, y desestructúrelos en variables, en bucles y en intercambios.

Un record agrupa varios valores sin tener que crear una clase. Puede tener campos posicionales, como (double, double, double), o con nombre, como ({String city, double celsius}). El typedef da a este último un nombre corto, Reading, que después se usa como cualquier otro tipo.
summarize devuelve tres valores a la vez: el mínimo, el máximo y la media. En main, final (low, high, avg) = ... los desestructura: es un patrón que deshace el record en tres variables de una sola vez. Antes de Dart 3 habría hecho falta una clase auxiliar o una lista sin tipos.
En el for, el patrón (:city, :celsius) toma los campos con nombre en variables que se llaman igual; :city es la forma corta de city: city. Así el bucle se lee casi como una frase y solo avisa de las ciudades que pasan de 30 grados.
Los campos con nombre se leen por su nombre (first.city) y los posicionales con $1, $2…; por eso summarize([1, 2]).$2 es el máximo, 2.0. Los records tienen igualdad por valor: dos records con los mismos campos son == aunque se hayan creado por separado. Por último, (a, b) = (b, a) intercambia dos variables sin necesitar una auxiliar.
Código · main.dart
// A record type with named fields, given a short name.typedef Reading = ({String city, double celsius});// Returning a positional record: three values, no helper class.(double, double, double) summarize(List<double> values) { final sorted = [...values]..sort(); final average = values.reduce((a, b) => a + b) / values.length; return (sorted.first, sorted.last, average);}void main() { final List<Reading> readings = [ (city: 'Madrid', celsius: 31.5), (city: 'Bilbao', celsius: 22.0), (city: 'Seville', celsius: 36.2), (city: 'Vigo', celsius: 19.8), ]; // Destructure the result into three variables at once. final (low, high, avg) = summarize([for (final r in readings) r.celsius]); print('Low $low, high $high, average ${avg.toStringAsFixed(1)}'); // :city is short for city: city (take the field into a variable). for (final (:city, :celsius) in readings) { if (celsius > 30) print('Heat warning in $city ($celsius C)'); } final first = readings.first; print('Fields: ${first.city}, positional: ${summarize([1, 2]).$2}'); print('Equal by value: ${(city: 'Vigo', celsius: 19.8) == readings[3]}'); var (a, b) = ('left', 'right'); (a, b) = (b, a); // swap without a temporary variable print('Swapped: $a $b');}Salida · dart run main.dart
Low 19.8, high 36.2, average 27.4 Heat warning in Madrid (31.5 C) Heat warning in Seville (36.2 C) Fields: Madrid, positional: 2.0 Equal by value: true Swapped: right left
Para recordar
- Un record agrupa valores sin crear una clase:
(1, 'a')o(x: 1, y: 2). - Devolver un record es la forma natural de devolver varios valores.
final (a, b) = record;desestructura en variables.:campotoma un campo con nombre en una variable del mismo nombre.- Los records se comparan por valor.
Ejercicio
Haga que summarize devuelva un record con nombre, ({double min, double max, double avg}), y cambie la desestructuración por final (:min, :max, :avg) = ....