# Extension Methods en Dart
Los Extension Methods, introducidos en Dart 2.7, te permiten agregar funcionalidad a librerías existentes sin modificar su código fuente y sin crear subclases.
## Sintaxis Básica
```dart
extension on {
// Métodos, getters, setters
}
```
### Ejemplo: String Extensions
```dart
extension StringUtils on String {
// Método nuevo
bool get isValidEmail {
return contains('@') && contains('.');
}
// Capitalizar primera letra
String capitalize() {
if (isEmpty) return this;
return '${this[0].toUpperCase()}${substring(1)}';
}
// Operador
String operator &(String other) => '$this $other';
}
void main() {
String email = '[email protected]';
// Uso natural, como si fuera parte de la clase String
if (email.isValidEmail) {
print(email.capitalize());
}
print('Hello' & 'World'); // "Hello World"
}
```
## Extensiones en Flutter
Son extremadamente útiles para simplificar código de UI repetitivo.
### 1. Context Extensions
Evita escribir `MediaQuery.of(context)` o `Theme.of(context)` repetidamente.
```dart
extension ContextExtensions on BuildContext {
// Dimensiones
double get width => MediaQuery.of(this).size.width;
double get height => MediaQuery.of(this).size.height;
// Tema
ThemeData get theme => Theme.of(this);
TextTheme get textTheme => Theme.of(this).textTheme;
ColorScheme get colors => Theme.of(this).colorScheme;
// Navegación
void push(Widget page) {
Navigator.of(this).push(MaterialPageRoute(builder: (_) => page));
}
void pop() => Navigator.of(this).pop();
}
// Uso en Widget
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: context.width * 0.8, // ✅ Más limpio
color: context.colors.primary,
child: Text(
'Hello',
style: context.textTheme.headline6,
),
);
}
}
```
### 2. Widget Extensions (Padding, Center, etc.)
Estilo "Modifier" similar a SwiftUI.
```dart
extension WidgetExtensions on Widget {
Widget paddingAll(double value) => Padding(
padding: EdgeInsets.all(value),
child: this,
);
Widget center() => Center(child: this);
Widget expanded({int flex = 1}) => Expanded(
flex: flex,
child: this,
);
}
// Uso encadenado
Widget build(BuildContext context) {
return Text('Hello')
.paddingAll(16.0)
.center()
.expanded();
}
```
### 3. Iterable Extensions
Operaciones útiles en listas.
```dart
extension IterableExtensions on Iterable {
// Obtener elemento o null si fuera de rango
T? getOrNull(int index) {
if (index < 0 || index >= length) return null;
return elementAt(index);
}
// Separar elementos con un separador
Iterable separate(T separator) sync* {
final iterator = this.iterator;
if (!iterator.moveNext()) return;
yield iterator.current;
while (iterator.moveNext()) {
yield separator;
yield iterator.current;
}
}
}
// Uso
final list = [1, 2, 3];
print(list.getOrNull(10)); // null
// Útil en Rows/Columns para agregar espacios
final widgets = [Text('A'), Text('B')];
final spaced = widgets.separate(SizedBox(width: 10));
```
## Extensiones Genéricas
Puedes extender tipos genéricos.
```dart
extension ListExtensions on List {
// Swap seguro
void safeSwap(int index1, int index2) {
if (index1 >= 0 && index1 < length && index2 >= 0 && index2 < length) {
final temp = this[index1];
this[index1] = this[index2];
this[index2] = temp;
}
}
}
```
## Resolución de Conflictos
Si dos extensiones definen el mismo método, Dart te pedirá que seas explícito o importes solo una.
```dart
// Si hay conflicto:
ExtensionName(objeto).metodo();
```
## Conclusión
Los Extension Methods son una herramienta fantástica para:
- **Legibilidad**: Código más limpio y expresivo.
- **Utilidad**: Agregar helpers a clases que no controlas (SDK, librerías).
- **Productividad**: Reducir boilerplate en Flutter.
¡Úsalos con responsabilidad! No conviertas todo en una extensión.
Este apartado profundiza en los conceptos clave, proporcionando ejemplos prácticos y mejores prácticas para su aplicación en proyectos reales.
Al comprender estos detalles, podrás diseñar soluciones más robustas, mantenibles y escalables en tus aplicaciones Flutter y Dart.