← Dart EspañolChapter 12 of 13

Genericos

## Objetivos de Aprendizaje - Comprender tipos genericos - Crear clases y funciones genericas - Dominar parametros de tipo limitados - Aprender restricciones de tipo ## Por Que Genericos? ### Sin Genericos ```dart class Stack { List _items = []; void push(dynamic item) => _items.add(item); dynamic pop() => _items.removeLast(); } void main() { var stack = Stack(); stack.push(1); stack.push('string'); // Permitido pero no seguro var item = stack.pop(); // print(item.length); // Error en tiempo de ejecucion si item es int! } ``` ### Con Genericos ```dart class Stack { List _items = []; void push(T item) => _items.add(item); T pop() => _items.removeLast(); } void main() { var intStack = Stack(); intStack.push(1); // intStack.push('string'); // Error! var stringStack = Stack(); stringStack.push('hello'); print(stringStack.pop().length); // 5 } ``` ## Clases Genericas ### Ejemplo Box ```dart class Box { T _value; Box(this._value); T get value => _value; void set value(T value) => _value = value; } void main() { var intBox = Box(42); print(intBox.value); // 42 var stringBox = Box('Hola'); print(stringBox.value); // Hola var dynamicBox = Box(42); // Funciona pero pierde seguridad de tipos // dynamicBox.value es aun int, pero el compilador no lo sabe } ``` ### Multiples Parametros de Tipo ```dart class Pair { K first; V second; Pair(this.first, this.second); @override String toString() => '($first, $second)'; } void main() { var pair = Pair('edad', 30); print(pair); // (edad, 30) var entry = Pair.of(1, 'uno'); print(entry); // (1, uno) } ``` ## Funciones Genericas ### Funcion Generica Basica ```dart T first(List list) { if (list.isEmpty) { throw Exception('Lista vacia'); } return list.first; } void main() { print(first([1, 2, 3])); // 1 print(first(['a', 'b', 'c'])); // a } ``` ### Metodo Generico ```dart class Utils { static T maximum>(T a, T b) { return a.compareTo(b) > 0 ? a : b; } } void main() { print(Utils.maximum(5, 10)); // 10 print(Utils.maximum('manzana', 'platano')); // platano } ``` ## Parametros de Tipo Limitados ### Restriccion extends ```dart // T debe extender num (int, double, etc.) class NumericBox { T _value; NumericBox(this._value); T square() => _value * _value as T; } void main() { var intBox = NumericBox(5); print(intBox.square()); // 25 var doubleBox = NumericBox(3.5); print(doubleBox.square()); // 12.25 // NumericBox(); // Error: String no extiende num } ``` ### Multiples Limites ```dart class ComparablePair, V extends Comparable> { K key; V value; ComparablePair(this.key, this.value); bool isKeyGreater() => key.compareTo(key) > 0; } ``` ## Colecciones Genericas ### List ```dart void main() { List numbers = [1, 2, 3, 4, 5]; List names = ['Alice', 'Bob', 'Charlie']; // List puede contener cualquier cosa List mixed = [1, 'dos', 3.0]; } ``` ### Map ```dart void main() { Map ages = { 'Alice': 30, 'Bob': 25, }; Map ids = { 1: 'uno', 2: 'dos', }; } ``` ### Set ```dart void main() { Set numbers = {1, 2, 3, 4, 5}; Set uniqueNames = {'Alice', 'Bob', 'Alice'}; // {'Alice', 'Bob'} } ``` ## Interfaces Genericos ### Interfaz Generico ```dart abstract class Repository { Future getById(String id); Future> getAll(); Future save(T item); } class UserRepository implements Repository { @override Future getById(String id) async => User(id); @override Future> getAll() async => []; @override Future save(User item) async {} } class User { final String id; User(this.id); } ``` ## Alias Genericos ### Typedef ```dart typedef StringMapper = String Function(String); typedef KeyValuePair = MapEntry; typedef NumberList = List; void main() { StringMapper mapper = (s) => s.toUpperCase(); print(mapper('hola')); // HOLA NumberList numbers = [1, 2, 3.0]; print(numbers); // [1, 2, 3.0] } ``` ## Restricciones de Tipo ### Clausula where ```dart // Mostrar items que son comparables y serializables class Collection> where T extends Serializable { void sortAndPrint() { // T es tanto Comparable como Serializable } } abstract class Serializable { String toJson(); } ``` ## Varianza ### Covarianza (out) ```dart // T solo puede producirse, no consumirse class Producer { T produce() => throw UnimplementedError(); } // Parametros de tipo covariantes permiten: // Producer es subtipo de Producer ``` ### Contravarianza (in) ```dart // T solo puede consumirse, no producirse class Consumer { void consume(T item) {} } // Parametros de tipo contravariantes permiten: // Consumer es subtipo de Consumer ``` ## Restricciones Genericas ### Restricciones Comunes ```dart // T debe ser no anulable class NonNullBox { T _value; NonNullBox(this._value); } // T debe tener constructor por defecto class GenericFactory { T create() => throw UnimplementedError() as T; } ``` ## Resumen - Genericos: `` para parametros de tipo - Clases genericas: `class Box {...}` - Funciones genericas: `T func(...) {...}` - Limitados: `T extends SomeType` - Colecciones: `List`, `Map`, `Set` - `typedef` crea alias de tipos - Varianza: `out` (covariante), `in` (contravariante) - Los genericos proporcionan seguridad de tipos y reducen duplicacion de codigo

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →