Dart Enums y Símbolos
Los enums (enumeraciones) se utilizan para definir un conjunto de constantes con nombre, lo que hace que el código sea más legible.
Este capítulo presenta la forma de definir enums en Dart, los enums mejorados (con métodos y propiedades), y los tipos Symbol y Rune.
Definición de enum (enumeración)
Un enum es un tipo especial de clase que se utiliza para representar un número fijo de valores constantes.
El escenario más típico es representar opciones limitadas como estados, direcciones, colores, etc.
Ejemplo
enum Status {
pending, // Pendiente
approved, // Aprobado
rejected, // Rechazado
cancelled, // Cancelado
}
void main() {
// Usar valores del enum
Status currentStatus = Status.pending;
print('Estado actual: $currentStatus');
// Obtener el índice mediante .index (empieza desde 0)
print('Valor del índice: ${currentStatus.index}'); // 0
// Obtener todos los valores del enum mediante .values
print('Todos los estados: ${Status.values}');
// Iterar sobre todos los valores del enum
for (var status in Status.values) {
print('Estado EJEMPLO: $status, índice: ${status.index}');
}
// Obtener el valor del enum a partir de una cadena
Status parsed = Status.values.byName('approved');
print('Estado analizado: $parsed');
// Usar el enum en un switch
switch (currentStatus) {
case Status.pending:
print('Pedido pendiente');
break;
case Status.approved:
print('Pedido aprobado');
break;
case Status.rejected:
print('Pedido rechazado');
break;
case Status.cancelled:
print('Pedido cancelado');
break;
}
}
当前状态: Status.pending 索引值: 0 所有状态: [Status.pending, Status.approved, Status.rejected, Status.cancelled] EJEMPLO 状态: Status.pending, 索引: 0 EJEMPLO 状态: Status.approved, 索引: 1 EJEMPLO 状态: Status.rejected, 索引: 2 EJEMPLO 状态: Status.cancelled, 索引: 3 解析出的状态: Status.approved 订单待处理
Los enums y switch son una combinación perfecta. Cuando manejas todos los valores del enum en un switch, el compilador de Dart verifica si has cubierto todos los casos. Esto evita bugs causados por ramas omitidas.
Enums mejorados (con métodos y propiedades)
Dart 3.0 introdujo los enums mejorados (Enhanced Enums), que permiten que los enums tengan campos, métodos y constructores.
Ejemplo
enum HttpStatus {
// Los valores del enum pasan parámetros a través del constructor
ok(200, 'Solicitud exitosa'),
created(201, 'Recurso creado'),
badRequest(400, 'Error de solicitud'),
unauthorized(401, 'No autorizado'),
notFound(404, 'Recurso no encontrado'),
serverError(500, 'Error interno del servidor');
// Variables miembro: cada valor del enum tiene code y message
final int code;
final String message;
// Constructor: debe ser const
const HttpStatus(this.code, this.message);
// Métodos del enum
bool get isSuccess => code >= 200 && code < 300;
bool get isClientError => code >= 400 && code < 500;
bool get isServerError => code >= 500;
// Método estático: busca el enum según el código de estado
static HttpStatus? fromCode(int code) {
try {
return HttpStatus.values.firstWhere((s) => s.code == code);
} catch (_) {
return null;
}
}
}
void main() {
var status = HttpStatus.notFound;
print('Estado HTTP EJEMPLO: $status');
print('Código de estado: ${status.code}');
print('Mensaje: ${status.message}');
print('¿Es exitoso?: ${status.isSuccess}');
print('¿Es error de cliente?: ${status.isClientError}');
// Usar el método estático para buscar
var found = HttpStatus.fromCode(201);
if (found != null) {
print('Estado encontrado: ${found.message}');
}
var unknown = HttpStatus.fromCode(999);
print('Código de estado desconocido: $unknown');
}
EJEMPLO HTTP 状态: HttpStatus.notFound 状态码: 404 Mensaje: 资源未找到 是否成功: false 是否客户端错误: true 找到状态: 资源已创建 未知状态码: null
Los enums mejorados transforman el enum de un "conjunto de constantes con nombre" a un "tipo con comportamiento", permitiendo encapsular la lógica relacionada con el enum.
El constructor de un enum mejorado debe ser const y las variables miembro deben ser final. Esto se debe a que los valores del enum son en sí mismos constantes en tiempo de compilación.
El tipo Symbol
Symbol representa identificadores en un programa Dart (nombres de variables, nombres de funciones, etc.).
No se usa comúnmente en el desarrollo diario; se utiliza principalmente en escenarios de reflexión (Reflection) y generación de código.
Ejemplo
// Crear un Symbol usando el prefijo #
Symbol sym1 = #ejemplo;
Symbol sym2 = #helloWorld;
print('Symbol 1: $sym1'); // Symbol("ejemplo")
print('Symbol 2: $sym2'); // Symbol("helloWorld")
// Comparación de Symbols
Symbol sym3 = #ejemplo;
print('sym1 == sym3: ${sym1 == sym3}'); // true
// Symbol se puede usar como clave de un Map
var metadata = {
#author: 'EJEMPLO',
#version: '1.0.0',
#description: 'Tutorial de Dart',
};
print('Autor: ${metadata[#author]}');
}
Symbol 1: Symbol("ejemplo")
Symbol 2: Symbol("helloWorld")
sym1 == sym3: true
作者: EJEMPLO
Los Symbols generalmente se minifican después de la compilación de Dart, por lo que no debes depender del resultado de Symbol("ejemplo").toString() para tomar decisiones lógicas. El uso correcto de Symbol es realizar operaciones de reflexión mediante la librería dart:mirrors.
Rune y Unicode
Rune es el tipo que representa los puntos de código Unicode en Dart.
En Dart, las cadenas son secuencias codificadas en UTF-16.
Para caracteres fuera del plano básico multilingüe (BMP), como los emojis, se necesita usar Rune para procesarlos.
Ejemplo
// Obtener los puntos de código Unicode de una cadena
String text = 'EJEMPLO';
print('Carácter: $text');
print('Lista de puntos de código: ${text.runes.toList()}');
// Iterar sobre cada carácter y su punto de código
for (var char in text.runes) {
print('${String.fromCharCode(char)} -> U+${char.toRadixString(16).toUpperCase().padLeft(4, '0')}');
}
// Crear un carácter a partir de un punto de código
var heart = String.fromCharCode(0x2764);
print('Corazón: $heart');
// Manejar caracteres de múltiples puntos de código (como algunos emojis)
var smile = '\u{1F600}'; // Usar la sintaxis \u{} para representar caracteres fuera del BMP
print('Cara sonriente: $smile');
// Obtener los puntos de código de un carácter de múltiples puntos de código
print('Puntos de código de la cara sonriente: ${smile.runes.map((r) => 'U+${r.toRadixString(16).toUpperCase()}').toList()}');
}
字符: EJEMPLO 码点列表: [82, 85, 78, 79, 79, 66] R -> U+0052 U -> U+0055 N -> U+004E O -> U+004F O -> U+004F B -> U+0042 心形: ❤ 笑脸: 😀 笑脸码点: [U+1F600]
En la mayor parte del desarrollo diario no necesitas manipular Rune directamente; las cadenas por sí solas ya manejan bien Unicode.
Rune se usa principalmente cuando se necesita manipular con precisión los puntos de código de los caracteres, como en escenarios de bajo nivel como editores de texto, renderizado de fuentes, etc.
Otras extensiones