Dart — Records

2024-01-14T18:00:00-05:00 | 6 minutos de lectura | Actualizado en 2025-01-24T07:42:46-05:00

jaimetellezb
Dart — Records

Tabla de Contenido

Introducción

Los Records son una característica agregada en Dart 3.0, similar a la desestructuración que tienen otros lenguajes como JavaScript, ayuda mucho cuando necesitamos acceder a atributos específicos y no objetos completos.

Records

Los Records permiten agrupar múltiples valores de diferentes tipos en uno anónimo(No tienen un nombre específico como clases) e inmutable(Una vez creados, sus valores no se pueden cambiar). A diferencia de otros tipos de colección, los Records son de tamaño fijo y tipados.

Sintaxis de los Records

La sintaxis de los Records son listas delimitadas por comas de campos con nombres o posicionales y están encerrados entre paréntesis.

Ejemplos expresiones de records

// posicional y nombres
var record = ('first', a: 2, b: true, 'last');
print(record.$1);
print(record.a);
print(record.b);
print(record.$2);

// posicional
var numbers = (1, 2, 3);
print(numbers.$1);
print(numbers.$2);
print(numbers.$3);

// nombres
var point = (latitude: 10.0, longitude: 20.0);
print(point.latitude);
print(point.longitude);

Los Records también tienen las anotaciones de tipo de record, que son listas de tipos delimitadas por comas y encerradas entre paréntesis. Puede utilizar anotaciones de tipo de record para definir tipos de retorno y tipos de parámetros.

Ejemplos de anotaciones de tipo

// intercambiar la posición de los valores de entrada
(int, int) swap((int, int) record) {
var (a, b) = record;
return (b, a);
}

void main() {
var res = swap((3, 4));
print(res);
}

// anotación de tipo de registro(record) en una variable
(String, int) record;

// Se inicializa con expresiones de registro (records)
record = ('Espera un String', 4567);

En una anotación de tipo de registro(record), los campos con nombre van dentro de una sección delimitada por llaves de pares de tipo y nombre, después de todos los campos posicionales. En una expresión de registro, los nombres van antes de cada valor de campo, seguidos de dos puntos.

// Declaración de anotación de tipo por nombre
({String a, bool b}) record;

// inicializa por expresión de registro(record)
record = (a: 'Esto es:', b: true);

En una anotación de tipo de registro(record), también puede nombrar los campos posicionales, pero estos nombres son solamente para documentación y no afectan al tipo de registro.

(int a, int b) recordA = (1, 2);
(int x, int y) recordX = (3, 4);

recordA = recordX;

Esto es similar a cómo los parámetros posicionales en una declaración de función pueden tener nombres, pero esos nombres no afectan la firma de la función.

Campos de Registro (record)

Los campos de registro son accesibles a través de los getters. Los registros son inmutables, por lo que los campos no tienen setters.

Los campos nombrados exponen a los getters del mismo nombre. Los campos posicionales exponen a los getters del nombre $<position>, esto quiere decir, que los campos posicionales accedemos a sus valores con $1, $2 si hay 2 campos, si hay 3 sería hasta $3 y para los campos nombrados si accedemos mediante el nombre dado.

var record = (latitude: 10.0, 'latidute', longitude: 20.0, 'longitude');
print(point.latitude);
print(point.$1);
print(point.longitude);
print(point.$2);

Para agilizar aún más el acceso al campo de registro, podemos usar los patrones de: desestructuración de múltiples retornos y la desestructuración de instancias de clases.

Desestructuración de múltiples retornos

Los Records permiten agregar y devolver múltiples valores desde una sola llamada a una función. Los patrones agregan la capacidad de desestructurar los campos de un registro directamente en variables locales. En lugar de declarar individualmente nuevas variables locales para cada campo de registro.

// sin desestructuración
var info = userInfo(json);
var name = info.$1;
var age = info.$2;

// con desestructuración
void main() {
var (name, age) = dogInfo();

print(name);
print(age);
}

(String name, int age) dogInfo() {
return ('Coco', 10);
}

Desestructuración de instancias de clases

Los patrones de objeto coinciden con los tipos de objeto nombrados, lo que le permite desestructurar sus datos utilizando los captadores que la clase del objeto ya expone.

Para desestructurar una instancia de una clase, use el tipo nombrado, seguido de las propiedades para desestructurar entre paréntesis.

final Foo myFoo = Foo(one: 'one', two: 2);
var Foo(:one, :two) = myFoo;
print('one $one, two $two');

Tipos de Records

No hay declaración de tipo para tipos de registro individuales. Los registros se escriben estructuralmente según los tipos de sus campos. Cada campo de un registro tiene su propio tipo. Los tipos de campo pueden diferir dentro del mismo registro.

(num, Object) pair = (10, 'abc');

// Tipo estático es num, pero en tiempo de ejecución es int
var first = pair.$1;
// Tipo estático es Object, pero en tiempo de ejecución es String
var second = pair.$2;

Igualdad en Records

Dos registros son iguales si tienen la misma forma (conjunto de campos), y sus campos correspondientes tienen los mismos valores. Dado que el orden de los campos nombrados no es parte de la forma de un registro, el orden de los campos nombrados no afecta a la igualdad. Esto quiere decir que si el nombre de los campos de 2 records es diferente pero la misma cantidad y su declaración es posicional, entonces los records son iguales.

// si son parámetros posicionales
(int x, int y, int z) point = (1, 2, 3);
(int a, int b, int c) color = (1, 2, 3);

print(point == color); // true

// si son parámetros con nombres
({int x, int y, int z}) point2 = (x: 1, y: 2, z: 3);
({int a, int b, int c}) color2 = (a: 1, b: 2, c: 3);

print(point == color); // false

Los Records definen automáticamente hashCode y == métodos basados en la estructura de sus campos.

Múltiples retornos

Los registros permiten que las funciones devuelvan varios valores agrupados. Para recuperar valores de registro de un retorno, desestructure los valores en variables locales utilizando la coincidencia de patrones.

(String, int, String) dogInfo(Map<String, dynamic> json) {
return (json['name'] as String, json['age'] as int, json['color'] as String);
}

final json = <String, dynamic>{
'name': 'Coco',
'age': 10,
'color': 'black',
};

// Desestructuración
var (name, name, color) = dogInfo(json);

/* Es lo mismo que:
var info = dogInfo(json);
var name = info.$1;
var age = info.$2;
var color = info.$3;
*/

Conclusión

Los Records son una característica muy potente para trabajar exactamente con los datos que necesitamos y de una forma más fácil y organizada.

¡Gracias por leer!

Fuentes

© 2022 - 2025 jaimetellezb - Compartir guías y tutoriales de programación.

🌱 Powered by Hugo with theme Dream.

Sobre mí

alt

Ingeniero de software

Hola, bienvenidos a mi blog sobre guías y tutoriales de programación.

Aquí podrás encontrar guías y tutoriales sobre algunos temas de tecnología en general. La idea es poder ayudar a que ciertas cosas como configuraciones de nuevas herramientas sean más fáciles de abordar y utilizar. También pequeños proyectos donde se usen diferentes tecnologías como ejemplo.

Enlaces sociales