Generic — la esencia de los tipos genéricos y los parámetros T

Autor: IT Sectr Publicado: 2026-06-18 Tiempo de lectura: 10 min

Generic (programación genérica) — es un mecanismo de Swift que permite escribir tipos y funciones con un tipo parametrizado . En lugar de duplicar código para Int, String y estructuras personalizadas, el desarrollador crea una solución genérica única que funciona con cualquier tipo, manteniendo la tipificación estricta. El compilador sustituye el tipo concreto en el momento de uso, garantizando seguridad sin perder rendimiento. Según Swift Book, 2025, los parámetros genéricos son una de las características clave del lenguaje, que forman la base de la biblioteca estándar y SwiftUI.

Puntos Clave

  • Generic — mecanismo de programación genérica con parámetros de tipo
  • Funciones con parámetros genéricos funcionan con cualquier tipo sin duplicar código
  • Restricciones where limitan el ámbito de los genéricos a tipos que cumplen condiciones
  • Associated Types en protocolos permiten que los protocolos sean genéricos
  • El compilador genera código especializado para cada tipo concreto

¿Qué es Generic en Swift?

Generic (tipo genérico) — es una construcción sintáctica de Swift que permite escribir código flexible y reutilizable con parametrización de tipos. En lugar de un tipo concreto, se escribe un marcador de posición entre corchetes angulares — normalmente , pero se puede usar cualquier nombre. Los genéricos forman la base de SwiftUI (View, some View), la biblioteca estándar (Array, Optional) y Combine.

Por qué se necesitan los genéricos

Sin genéricos, habría que escribir funciones separadas para cada tipo: swapInts, swapStrings, swapDates. Una función genérica swap reemplaza las tres variantes con una sola declaración. Esto reduce la duplicación, mejora la legibilidad y disminuye la probabilidad de errores al copiar código.

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

var x = 10
var y = 20
swapValues(&x, &y)

El compilador de Swift genera código especializado para cada uso concreto de un genérico. Esto significa que la función genérica swapValues no tiene sobrecarga en comparación con una función escrita a mano para Int. Swift no usa borrado de tipos como Java — los genéricos existen tanto en tiempo de compilación como en tiempo de ejecución (aunque la optimización puede especializarlos).

Funciones Genéricas con Parámetro T

Funciones genéricas son funciones que aceptan uno o más parámetros de tipo. Los parámetros de tipo se especifican después del nombre de la función entre corchetes angulares: . Pueden usarse en la firma: tipo de argumento, tipo de retorno y dentro del cuerpo de la función.

Múltiples Parámetros de Tipo

Una función puede tener múltiples parámetros genéricos. Por ejemplo, la función findKey toma un diccionario con claves K y valores V. Cada parámetro de tipo es único y puede usarse en restricciones.

swift
func findKey<K: Hashable, V>(
    for value: V,
    in dictionary: [K: V]
) -> K? where V: Equatable {
    for (key, dictValue) in dictionary {
        if dictValue == value {
            return key
        }
    }
    return nil
}

Las restricciones K: Hashable y where V: Equatable aseguran que findKey solo puede llamarse con un diccionario cuyas claves sean hashable y valores equatable. Tales restricciones no son burocracia sino una necesidad: sin Hashable no se puede indexar una búsqueda por clave, sin Equatable no se puede comparar value con dictValue.

Restricciones de Tipo mediante where

where — es una palabra clave de Swift que impone restricciones adicionales a los parámetros genéricos. A diferencia de simplemente especificar un protocolo entre corchetes angulares (), where permite expresar condiciones más complejas: conformidad con múltiples protocolos, relaciones entre parámetros de tipo y refinamiento de associated types.

Sintaxis de where

La cláusula where se escribe después de la firma de la función o tipo, antes de la llave de apertura. En where se puede especificar que T: Comparable & Hashable (conforme a dos protocolos simultáneamente), o que T.U == Int (concretar un associated type).

swift
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
}

extension Container where Item: Comparable {
    func isSorted() -> Bool {
        // Implementation available only if Item: Comparable
        return true
    }
}

La extensión con where añade métodos solo para aquellos tipos que cumplen la condición. Container obtendrá el método isSorted, mientras que Container no, porque Any no es Comparable. Este es un poderoso mecanismo de funcionalidad condicional.

Associated Types en Protocolos

Associated Types (tipos asociados) — son una forma de hacer que un protocolo sea genérico sin especificar un tipo concreto en la etapa de declaración. En lugar de , el protocolo declara un associatedtype, que se concreta en la implementación. Esto es especialmente importante para colecciones: el protocolo Sequence no sabe qué elementos contendrá la secuencia.

Vinculación de Associated Types mediante where

Usando where se pueden establecer relaciones entre associated types de diferentes protocolos. Por ejemplo, se puede exigir que el Item de un protocolo coincida con Iterator.Element de otro. Esto garantiza la compatibilidad de tipos a nivel de compilación.

swift
protocol StackProtocol {
    associatedtype Element
    mutating func push(_ item: Element)
    mutating func pop() -> Element?
}

struct IntStack: StackProtocol {
    typealias Element = Int
    private var items: [Int] = []
    
    mutating func push(_ item: Int) { items.append(item) }
    mutating func pop() -> Int? { items.popLast() }
}

IntStack concreta Element como Int usando typealias. El compilador verifica que todos los requisitos del protocolo se cumplen con este tipo. Sin associated types, habría que escribir StackProtocol con un protocolo genérico, pero Swift usa associated types por consistencia con los puentes de Objective-C y mejor legibilidad.

Generic en Extensiones y Subíndices

Extensiones genéricas permiten añadir métodos a un tipo genérico con restricciones adicionales. Este es el patrón de “conformidad condicional”, donde un tipo obtiene funcionalidad solo bajo ciertas condiciones. Los subíndices también pueden ser genéricos.

Subíndice Genérico

Un subíndice puede ser genérico: acepta parámetros genéricos entre corchetes angulares. Esto es útil para el acceso seguro a colecciones con índices arbitrarios, donde el índice puede ser de diferentes tipos.

swift
extension Array where Element: Numeric {
    func sum() -> Element {
        return reduce(0, +)
    }
}

extension Array {
    subscript<Indices: Sequence>(indices: Indices) -> [Element]
        where Indices.Element == Int {
        return indices.map { self[$0] }
    }
}

Esta construcción proporciona una composición potente: el método sum aparece solo en arrays numéricos, y el subíndice con índices arbitrarios funciona con cualquier secuencia de índices enteros. El compilador gestiona la visibilidad de estos miembros basándose en las condiciones where.

Errores Comunes al Trabajar con Genéricos

Errores al usar genéricos a menudo están relacionados con restricciones incorrectas o el intento de usar genéricos donde se necesita un tipo concreto. Veamos tres escenarios comunes que enfrentan los desarrolladores.

Parametrización Excesiva

Añadir parámetros genéricos donde un tipo concreto es suficiente es un antipatrón. Si una función siempre trabaja con String, no es necesario hacerla . Esto complica el código sin beneficio. Los genéricos se justifican cuando el tipo realmente varía, no para una “flexibilidad futura” abstracta.

Falta de Restricción where

Llamar a un método en un parámetro genérico sin especificar que el método existe es un error. no puede llamar a .count si no se especifica que T: Collection. Siempre añada restricciones a los parámetros de tipo, de lo contrario el compilador rechazará el código.

swift
// ❌ Error: value has no count method
func countElements<T>(value: T) -> Int { value.count }

// ✅ Works: T: Collection guarantees count exists
func countElements<T: Collection>(value: T) -> Int { value.count }

El error es claro: el genérico puede ser cualquier tipo, y el compilador no sabe si tiene count. La restricción Collection resuelve el problema. De manera similar para Equatable, Hashable, Numeric — especifique siempre el protocolo si planea llamar a métodos u operadores en el parámetro genérico.

Preguntas Frecuentes

¿Qué es Generic en Swift en términos simples?

Generic es una forma de escribir código que funciona con cualquier tipo, sin duplicar la misma lógica para Int, String y otros tipos. En lugar de un tipo concreto, se usa un marcador de posición , que es reemplazado por el tipo real en el momento de uso.

¿En qué se diferencia Generic de Any?

Generic preserva la información sobre el tipo concreto en tiempo de compilación, permitiendo al compilador verificar tipos y generar código optimizado. Any es borrado de tipo: cualquier valor puede pasarse, pero el tipo se pierde y se requiere conversión (as?).

¿Cómo restringir un Generic con un protocolo?

Use la sintaxis T: SomeProtocol entre corchetes angulares o una cláusula separada where T: SomeProtocol. Las restricciones garantizan que el parámetro genérico soporta métodos y propiedades específicos.

¿Qué es un Associated Type en un protocolo?

Associated Type (associatedtype) es un marcador de posición para un tipo dentro de un protocolo. El protocolo no especifica un tipo concreto sino que declara un associatedtype, que se concreta en la implementación: Array tiene Element, Dictionary tiene Key y Value.

¿Los genéricos son más rápidos o más lentos que los tipos concretos?

Swift compila el código genérico en versiones especializadas para cada tipo concreto. En la práctica, una función genérica para Int no es más lenta que una función escrita a mano para Int. No hay sobrecarga de abstracción.

Resumen

  • Generic — mecanismo de programación genérica con parámetro de tipo
  • Funciones y tipos con parámetros genéricos reemplazan múltiples implementaciones duplicadas
  • Restricciones where limitan el ámbito de los genéricos a condiciones necesarias
  • Associated Types permiten que los protocolos sean genéricos sin concretar en la declaración
  • Extensiones con where añaden funcionalidad solo cuando se cumplen condiciones
  • El compilador genera código especializado — los genéricos no añaden sobrecarga
  • Parametrización excesiva es un antipatrón — use genéricos solo cuando el tipo realmente varía

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también