Dart: Enums, Extension Methods y Records

Tres características que hacen a Dart más expresivo que un enum tradicional

🪐 1. Enhanced Enum (con datos y métodos)

Resultado:

Planeta.jupiter.gravedad
2.36
pesoEn(70)
165.2 kg en Júpiter

Elige un planeta

enum Planeta {
  mercurio(gravedad: 0.378),
  marte(gravedad: 0.377),
  jupiter(gravedad: 2.360),
  neptuno(gravedad: 1.140);

  const Planeta({required this.gravedad});
  final double gravedad;

  double pesoEn(double pesoTierra) => pesoTierra * gravedad;
}

print(Planeta.jupiter.pesoEn(70)); // 165.2
💡 Enhanced enums (Dart 2.17+)

Antes, un enum de Dart solo era una lista de valores. Ahora puede tener constructor, propiedades y métodos, como una clase normal — perfecto para modelar catálogos de valores fijos con comportamiento (estados de un pedido, tipos de suscripción, etc.).

🧩 2. Extension Methods

Resultado:

7.esPar
false
7.esPrimo
true

Prueba un número

extension NumeroUtil on int {
  bool get esPar => this % 2 == 0;

  bool get esPrimo {
    if (this < 2) return false;
    for (int i = 2; i <= this ~/ 2; i++) {
      if (this % i == 0) return false;
    }
    return true;
  }
}

print(7.esPar);   // falseprint(7.esPrimo); // true
💡 ¿Para qué sirven?

Las extension añaden métodos/getters a un tipo que ya existe (incluso int, String o widgets de Flutter que no puedes modificar), sin tener que heredar de él ni envolverlo en otra clase.

📦 3. Records y Patterns (Dart 3)

Resultado:

persona() (record)
(Marta, 20)
clasificar(persona())
Marta es

Construye un record

(String, int) persona() => ('Marta', 20);

// Destructuring: extraer los valores del recordfinal (nombre, edad) = persona();

String clasificar((String, int) p) => switch (p) {
  (_, int e) when e < 13 => 'niño/a',
  (_, int e) when e < 18 => 'adolescente',
  (_, int e) when e < 65 => 'adulto/a',
  _                      => 'jubilado/a',
};

print(clasificar(persona())); // 
💡 Records

Un record ((String, int)) te permite devolver varios valores desde una función sin tener que crear una clase solo para eso. Combinado con switch y patterns, puedes "desestructurar" y examinar su contenido de forma muy compacta.

🎯 Conceptos Clave

Enhanced enums

  • Constructor, propiedades, métodos
  • Cada valor es una instancia const

Extension methods

  • extension X on Tipo { ... }
  • Añade funciones sin heredar

Records & Patterns

  • (Tipo1, Tipo2) agrupa valores
  • switch + patterns para desestructurar

💪 Ejercicio Práctico

Combina las tres características

  1. Añade un valor tierra(gravedad: 1.0) al enum Planeta.
  2. Crea una extension on String con un getter esPalindromo.
  3. Crea una función que devuelva un record (double x, double y) representando un punto, y clasifícalo por cuadrante con switch.

Solución 1

enum Planeta {
  tierra(gravedad: 1.0),
  // ...resto de planetas  ;
  const Planeta({required this.gravedad});
  final double gravedad;
}

Solución 2

extension PalindromoUtil on String {
  bool get esPalindromo => this == split('').reversed.join('');
}

Solución 3

String cuadrante((double, double) punto) => switch (punto) {
  (> 0, > 0) => t('Cuadrante I'),
  (< 0, > 0) => t('Cuadrante II'),
  (< 0, < 0) => t('Cuadrante III'),
  (> 0, < 0) => t('Cuadrante IV'),
  _          => t('Sobre un eje'),
};