Fundamentos de Strings en Dart

Un String en Dart es una secuencia inmutable de unidades de código UTF-16. Esto significa que, una vez que creas una cadena de texto, no puedes modificar sus caracteres individualmente; cualquier “cambio” que realices es en realidad la creación de un nuevo objeto en memoria. Esta inmutabilidad es una decisión de diseño fundamental para que el manejo de memoria sea eficiente y seguro cuando pasas texto entre diferentes partes de tu programa. Usarás String siempre que necesites manejar texto, ya sea una simple palabra o un bloque enorme de datos. Si intentas cambiar un carácter mediante un índice, el compilador no te lo permitirá porque el contenido es fijo.

Cuando pidas la longitud de un texto con length, debes tener cuidado: Dart no cuenta “letras” o “emojis” como los ve un humano, sino que cuenta unidades de código UTF-16. Esto es necesario porque algunos caracteres complejos (como ciertos emojis) ocupan más de una unidad de memoria. Por eso, un emoji puede tener un length de 2 o más. Para contar caracteres reales (puntos de código Unicode), debes usar runes. Debes distinguir entre un codeUnit (el valor numérico de una unidad UTF-16) y una Rune (el código completo de un carácter Unicode), ya que esto evita errores lógicos al procesar texto que contiene símbolos especiales.

Para crear texto, tienes literales con comillas simples ' o dobles ", y para bloques extensos, las triples comillas ''' o """. Si necesitas escribir rutas de archivos con muchas barras invertidas, usa raw strings con el prefijo r. Para insertar variables dentro de un texto, la interpolación mediante $variable o ${expresion} es la forma más eficiente y legible, evitando el uso excesivo del operador +.

void main() {
  // Literales básicos y multilínea
  const String saludo = 'Hola, Dart';
  const String cita = """
    "Esta es una cita
    en varias líneas".
  """;

  // Raw strings: las barras invertidas se tratan como texto literal
  const String ruta = r'C:\usuarios\desarrollador\proyectos';

  // Interpolación: usamos $ para variables y ${} para expresiones
  const String nombre = 'Dev';
  const String version = '3.4';
  print('Hola $nombre, estás usando la versión ${version.substring(0,1)}');

  // El comportamiento de length con emojis (UTF-16)
  // El emoji 🚀 es un par de unidades de código (surrogate pair)
  const String emoji = '🚀';
  print('Emoji: $emoji');
  print('Unidades UTF-16 (length): ${emoji.length}'); // Resultado: 2
  print('Puntos de código (runes): ${emoji.runes.length}'); // Resultado: 1

  // Concatenación automática de literales adyacentes
  const String unido = 'Texto '
      'unido '
      'sin operadores';
  print(unido);

  // Secuencias de escape y Unicode
  // \u{XXXXX} permite definir puntos de código Unicode superiores
  print('Unicode: \u{1F44D}'); // Emoji de mano
}

Desglose del ejemplo

En el código anterior, la variable saludo es un String estándar. Para cita, usamos comillas triples, lo que permite que los saltos de línea se mantengan tal cual sin necesidad de usar \n. La variable ruta utiliza el prefijo r, convirtiéndola en una raw string; esto es vital para que la \ no intente escapar el siguiente carácter.

Fíjate en la interpolación de la línea de print: usamos $nombre porque es una variable simple, pero para version.substring(0,1) necesitamos ${} porque estamos ejecutando un método sobre un objeto.

El punto más crítico es el manejo del emoji. Al imprimir emoji.length, verás un 2. Esto sucede porque el emoji de cohete no cabe en una sola unidad de 16 bits de la especificación UTF-16 y requiere un “par de sustitución”. Sin embargo, emoji.runes.length nos devuelve 1, porque las runes representan el código Unicode real (el punto de código), que es lo que realmente nos interesa para contar caracteres “reales”.

Finalmente, la variable unido demuestra una característica de Dart: si pones dos literales de string uno al lado del otro, el compilador los une automáticamente sin necesidad de usar el operador +, lo que limpia mucho el código cuando defines constantes muy largas.

El error frecuente

void main() {
  // Error lógico común al validar longitud
  String input = 'Hola 🚀'; 
  
  // El usuario ve 6 caracteres: 'H','o','l','a',' ','🚀'
  // Pero la VM ve 7 unidades UTF-16 debido al emoji.
  if (input.length == 6) {
    print('El texto tiene 6 caracteres'); 
  } else {
    print('La longitud es ${input.length}, el usuario se equivoca');
  }
}

Si intentas validar la entrada de un usuario basándote en length para limitar la cantidad de caracteres, los emojis romperán tu lógica. Un emoji cuenta como 2 en length, pero solo como 1 para el usuario. Si necesitas contar caracteres “visuales”, usa input.runes.length.

14

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio