Records (Dart 3)
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy. Lección 86 de 110.
Dart 3 introdujo los registros: una forma ligera de agrupar varios valores sin crear una clase completa. Los registros son inmutables, tienen igualdad integrada y son perfectos para devolver varios valores desde una función o agrupar temporalmente datos relacionados.
Crea un registro envolviendo los valores entre paréntesis:
void main() {
// Un registro simple con dos valores
var point = (10, 20);
print(point.$1); // 10 - accede al primer elemento
print(point.$2); // 20 - accede al segundo elemento
// Registros con campos con nombre
var person = (name: 'Alice', age: 30);
print(person.name); // Alice
print(person.age); // 30
}Se accede a los campos posicionales con $1, $2, etc., mientras que los campos con nombre utilizan sus nombres directamente. Puedes mezclar ambos estilos en un solo registro.
Los registros destacan al devolver múltiples valores desde funciones; no es necesario crear una clase solo para devolver dos fragmentos de datos:
(int, int) divideWithRemainder(int a, int b) {
return (a ~/ b, a % b);
}
(String name, int age) getUser() {
return ('Bob', 25);
}
void main() {
var (quotient, remainder) = divideWithRemainder(17, 5);
print('$quotient remainder $remainder'); // 3 residuo 2
var (name, age) = getUser();
print('$name is $age'); // Bob is 25
}Los registros admiten automáticamente la igualdad basada en sus valores, lo que los hace convenientes para realizar comparaciones sin tener que implementar == por tu cuenta. Usa registros cuando necesites agrupaciones de datos simples e inmutables; usa clases cuando necesites métodos, mutabilidad o un comportamiento más complejo.
Desafío
Fácil¡Construyamos un sistema de coordenadas usando registros! Crearás funciones que trabajan con puntos 2D representados como registros, demostrando cómo los registros facilitan devolver y trabajar con múltiples valores relacionados sin crear clases completas.
Organizarás tu código en dos archivos:
geometry.dart: Crea funciones que usen registros para trabajar con datos de coordenadas:- Una función
createPoint(int x, int y)que devuelva un registro con los campos con nombrexyy. El tipo de retorno debe ser({int x, int y}) - Una función
midpoint(({int x, int y}) p1, ({int x, int y}) p2)que calcule y devuelva el punto medio entre dos puntos como un registro con campos con nombre. Usa división entera (~/) para el cálculo - Una función
distance(({int x, int y}) p1, ({int x, int y}) p2)que devuelva un registro con campos posicionales: la distancia horizontal (diferencia en x) y la distancia vertical (diferencia en y). El tipo de retorno debe ser(int, int). Calcula comop2.x - p1.xyp2.y - p1.y
- Una función
main.dart: Importa tu archivo de geometría y demuestra los registros en acción:- Crea dos puntos usando
createPoint: el punto A en(2, 4)y el punto B en(10, 8) - Imprime
Point A: ([x], [y])usando los campos con nombre - Imprime
Point B: ([x], [y])usando los campos con nombre - Calcula el punto medio e imprime
Midpoint: ([x], [y]) - Calcula la distancia y usa la desestructuración para extraer los valores en las variables
dxydy; después, imprimeDistance: dx=[dx], dy=[dy]
- Crea dos puntos usando
¡Observa cómo los registros te permiten devolver múltiples valores de forma clara: campos con nombre para mayor claridad cuando el significado es importante y campos posicionales cuando el contexto es obvio!
Salida esperada:
Point A: (2, 4)
Point B: (10, 8)
Midpoint: (6, 6)
Distance: dx=8, dy=4Pruébalo tú mismo
import 'geometry.dart';
void main() {
// TODO: Crear el punto A en (2, 4) usando createPoint
// TODO: Crear el punto B en (10, 8) usando createPoint
// TODO: Imprimir el Punto A usando campos con nombre: Point A: ([x], [y])
// TODO: Imprimir el Punto B usando campos con nombre: Point B: ([x], [y])
// TODO: Calcular el punto medio e imprimir: Midpoint: ([x], [y])
// TODO: Calcular la distancia y usar la desestructuración para extraer en dx y dy
// Luego imprimir: Distance: dx=[dx], dy=[dy]
}
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
1Fundamentos de POO
Archivos externosLibrerías e importacionesIntroducción a la POOClases vs. ObjetosLa palabra clave thisMétodosVariables de instanciaConceptos básicos de constructoresResumen - Calculadora sencilla4Seguridad de nulos
Introducción a la seguridad de nulosNulables vs No nulablesLos operadores ? y !Palabra clave Late y Null SafetyOperadores Null-awareNull Safety en clasesResumen - Sistema de perfil de usuario7Clases abstractas e interfaces
Clases abstractasMétodos abstractosInterfaces en DartInterfaces implícitasImplementar vs. ExtenderInterfaces múltiplesRepaso - Calculadora de figuras10Colecciones y Genéricos
Visión general de List, Set y MapColecciones con seguridad de tiposClases genéricasMétodos genéricosRestricciones genéricasIterable e IteratorResumen - Almacenamiento genérico13Conceptos avanzados de POO
Composición vs. HerenciaMétodos de extensiónClases invocablesClases selladas (Dart 3)Records (Dart 3)Patrones y coincidencia (3.0)Enums con métodos2Constructores en Dart
Constructor por defectoConstructores nombradosListas de inicializaciónConstructores constantesConstructores de fábricaConstructores de redireccionamientoResumen - Constructor de formas5Encapsulamiento
Miembros públicos vs. privadosLa convención del prefijo _Privacidad a nivel de libreríaProfundidad en Getters y SettersOcultamiento de informaciónResumen - Registros de estudiantes8Mixins
Introducción a los MixinsCreación de MixinsUso de múltiples MixinsPalabra clave on en MixinsMixin vs HerenciaMixin vs InterfazResumen - Sistema Animal11Métodos especiales
Sobrescritura de toString()Sobrescritura de hashCode y ==Interfaz ComparableMétodo call()Sobrescritura de noSuchMethodResumen - Colección personalizada14Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy3Propiedades de clase
Miembros de instancia vs. estáticosCampos Final y ConstVariables LateMétodos y campos estáticosGetters y SettersResumen - Gestor de cuentas bancarias6Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosLa anotación @overrideLa palabra clave final en clasesConstructores y herenciaResumen - Jerarquía de empleados9Polimorfismo
Fundamentos del polimorfismoPolimorfismo mediante interfacesComprobación de tipos en tiempo de ejecuciónLos operadores is y asPalabra clave covariantResumen - Procesador de pagos12POO Asíncrona
Futures y async/awaitFundamentos de StreamsStream ControllersConstructores asíncronosAsincronía en métodos de claseRepaso - Data Fetcher15Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón RepositoryPractica por tu cuenta: Compilador de Dart online