DMarlon Studio

Lección 7 · 7 de 20

Métodos de extensión · Dart

Añada métodos y getters a int, String o List en Dart con extensiones, también genéricas, sin heredar ni modificar esas clases.

Dart · Métodos de extensión en DMarlon Studio: el código del ejemplo y su salida en la terminal

Las extensiones añaden métodos y getters a tipos que no son suyos, como int, String o List, sin heredar de ellos ni envolverlos en otra clase. Se declaran con extension Nombre on Tipo y, dentro, this es el valor sobre el que se llama.

MoneyFormat añade a los enteros un getter eur, de modo que 1999.eur da 19.99 EUR. TextTools añade dos utilidades a String: capitalized (primera letra en mayúscula y el resto en minúscula) y toSlug(), que con dos expresiones regulares convierte un título en un texto apto para una URL. Fíjese en que dentro de la extensión se llama a trim() o a substring() sin prefijo, igual que en un método de la propia clase.

Stats extiende Iterable<int>, así que sirve para listas, conjuntos y cualquier iterable de enteros: total suma con fold y average divide entre length. Las extensiones se combinan con naturalidad: basket.average.round().eur redondea la media y le da formato con la primera extensión.

SafeIndex<T> es una extensión genérica: vale para una List de cualquier tipo, y at(7) devuelve null en lugar de lanzar RangeError. Las extensiones se eligen en tiempo de compilación según el tipo estático de la expresión, por lo que no funcionan sobre una variable dynamic.

Código · main.dart

// Extensions add methods to types you do not own, like int or String.extension MoneyFormat on int {  String get eur => '${(this / 100).toStringAsFixed(2)} EUR';}extension TextTools on String {  String get capitalized =>      isEmpty ? this : this[0].toUpperCase() + substring(1).toLowerCase();  String toSlug() => trim()      .toLowerCase()      .replaceAll(RegExp(r'[^a-z0-9]+'), '-')      .replaceAll(RegExp(r'^-|-$'), '');}extension Stats on Iterable<int> {  int get total => fold(0, (sum, n) => sum + n);  double get average => isEmpty ? 0 : total / length;}// Generic extension: works on a List of any type.extension SafeIndex<T> on List<T> {  T? at(int index) => index >= 0 && index < length ? this[index] : null;}void main() {  print(1999.eur);  print('mADRID'.capitalized);  print('  Advanced Dart: Records & Patterns! '.toSlug());  final basket = [1250, 899, 4500];  print('Total ${basket.total.eur}, average ${basket.average.round().eur}');  print('Item 1: ${basket.at(1)}, item 7: ${basket.at(7)}');}

Salida · dart run main.dart

19.99 EUR
Madrid
advanced-dart-records-patterns
Total 66.49 EUR, average 22.16 EUR
Item 1: 899, item 7: null

Para recordar

  • extension Nombre on Tipo añade miembros a tipos ajenos.
  • Dentro de la extensión, this es el valor sobre el que se llama.
  • Pueden ser getters, métodos e incluso operadores.
  • Admiten genéricos: extension X<T> on List<T>.
  • Se eligen por el tipo estático; no sirven con dynamic.

Ejercicio

Escriba una extensión sobre String con un getter initials que devuelva las iniciales en mayúsculas, de modo que 'ana belen ruiz'.initials dé ABR.