Generics en Swift para principiantes: para qué sirven y cómo usarlos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿Por qué no puedes prescindir de los Generics en Swift?

Imagina que necesitas escribir una función que sume dos números. Luego, una función para sumar dos cadenas. Y después, para arrays. Sin programación genérica (Generics), tendrías que crear una versión separada del código para cada tipo de datos. Esto no solo aumenta el volumen de código, sino que también dificulta su mantenimiento.

Los Generics en Swift son una herramienta poderosa que permite escribir código flexible, reutilizable y type-safe. Son la base de estructuras populares como Array, Dictionary y Optional. En este artículo, analizaremos para qué sirven los Generics, cómo usarlos en la práctica y por qué todo desarrollador principiante de iOS/macOS debe dominar este tema.



¿Qué son los Generics en palabras sencillas?

Generics (genéricos) es una forma de escribir código que funciona con cualquier tipo de datos, sin sacrificar la tipificación estricta de Swift. En lugar de especificar un tipo concreto (por ejemplo, Int o String), se utiliza un placeholder (generalmente la letra T), que se reemplaza por el tipo real al llamar a la función o crear la estructura.



El problema sin Generics

Supongamos que escribes una función para intercambiar los valores de dos variables. Sin Generics, tendrías que escribir algo así:

func swapInts(_ a: inout Int, _ b: inout Int) {    let temp = a    a = b    b = temp}

func swapStrings(_ a: inout String, _ b: inout String) { let temp = a a = b b = temp}

Esto es una duplicación evidente. Si necesitas intercambiar Double o tipos personalizados, la cantidad de funciones seguirá creciendo.



Solución con Generics

Una sola función universal reemplazará todas las anteriores:

func swapValues<T>(_ a: inout T, _ b: inout T) {    let temp = a    a = b    b = temp}

// Uso:var x = 10var y = 20swapValues(&x, &y) // x = 20, y = 10

var firstName = "Ana"var lastName = "García"swapValues(&firstName, &lastName) // firstName = "García"

Los corchetes angulares <T> declaran el placeholder del tipo. El compilador determina automáticamente que T es Int en el primer caso y String en el segundo. El código se vuelve conciso y seguro.



Cómo usar Generics: escenarios principales

Los Generics en Swift se aplican en funciones, estructuras, clases, enumeraciones y protocolos. Veamos los casos más comunes.



1. Funciones genéricas

Ya vimos el ejemplo con swapValues. Pero podemos ir más allá: crear una función que encuentre el índice de un elemento en un array:

func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {    for (index, element) in array.enumerated() {        if element == value {            return index        }    }    return nil}

let numbers = [1, 5, 9, 12]if let index = findIndex(of: 9, in: numbers) { print("Índice: \\(index)") // Índice: 2}

Observa <T: Equatable>. Esto es una restricción de tipo (type constraint). Estamos diciendo: «T debe cumplir con el protocolo Equatable para que podamos usar el operador ==». Sin esta restricción, el código no compilaría.



2. Tipos genéricos (estructuras y clases)

Creemos una estructura simple de «Pila» (LIFO) que pueda almacenar cualquier tipo:

struct Stack<Element> {    private var items: [Element] = []

mutating func push(_ item: Element) { items.append(item) }

mutating func pop() -> Element? { return items.popLast() }

func peek() -> Element? { return items.last }}

// Uso:var intStack = Stack<Int>()intStack.push(1)intStack.push(2)print(intStack.pop

Blogs

Book Recommendations