Generic — a essência dos tipos genéricos e parâmetros T

Autor: IT Sectr Publicado: 2026-06-18 Tempo de leitura: 10 min

Generic (programação genérica) — é um mecanismo do Swift que permite escrever tipos e funções com um tipo parametrizado . Em vez de duplicar código para Int, String e estruturas personalizadas, o desenvolvedor cria uma única solução genérica que funciona com qualquer tipo, mantendo a tipagem estrita. O compilador substitui o tipo concreto no ponto de uso, garantindo segurança sem perda de desempenho. De acordo com Swift Book, 2025, os parâmetros genéricos são um dos recursos-chave da linguagem, formando a base da biblioteca padrão e do SwiftUI.

Principais Conclusões

  • Generic — mecanismo de programação genérica com parâmetros de tipo
  • Funções com parâmetros genéricos funcionam com qualquer tipo sem duplicar código
  • Restrições where limitam o escopo de genéricos a tipos que atendem condições
  • Associated Types em protocolos permitem que protocolos sejam genéricos
  • O compilador gera código especializado para cada tipo concreto

O que é Generic em Swift?

Generic (tipo genérico) — é uma construção sintática do Swift que permite escrever código flexível e reutilizável com parametrização de tipo. Em vez de um tipo concreto, um placeholder é escrito entre colchetes angulares — geralmente , mas qualquer nome pode ser usado. Generics formam a base do SwiftUI (View, some View), da biblioteca padrão (Array, Optional) e do Combine.

Por que Generics são necessários

Sem generics, você teria que escrever funções separadas para cada tipo: swapInts, swapStrings, swapDates. Uma função genérica swap substitui todas as três variantes com uma única declaração. Isso reduz duplicação, melhora a legibilidade e diminui a chance de erros ao 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)

O compilador Swift gera código especializado para cada uso concreto de um generic. Isso significa que a função genérica swapValues não tem sobrecarga em comparação com uma função escrita à mão para Int. Swift não usa apagamento de tipo como Java — generics existem tanto em tempo de compilação quanto em tempo de execução (embora a otimização possa especializá-los).

Funções Genéricas com Parâmetro T

Funções genéricas são funções que aceitam um ou mais parâmetros de tipo. Os parâmetros de tipo são especificados após o nome da função entre colchetes angulares: . Eles podem ser usados na assinatura: tipo do argumento, tipo de retorno e dentro do corpo da função.

Múltiplos Parâmetros de Tipo

Uma função pode ter múltiplos parâmetros genéricos. Por exemplo, a função findKey recebe um dicionário com chaves K e valores V. Cada parâmetro de tipo é único e pode ser usado em restrições.

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
}

As restrições K: Hashable e where V: Equatable garantem que findKey só pode ser chamada com um dicionário cujas chaves sejam hashable e valores equatable. Tais restrições não são burocracia, mas necessidade: sem Hashable não se pode indexar uma busca por chave, sem Equatable não se pode comparar value com dictValue.

Restrições de Tipo via where

where — é uma palavra-chave do Swift que impõe restrições adicionais aos parâmetros genéricos. Ao contrário de simplesmente especificar um protocolo entre colchetes angulares (), where permite expressar condições mais complexas: conformidade com múltiplos protocolos, relações entre parâmetros de tipo e refinamento de associated types.

Sintaxe where

A cláusula where é escrita após a assinatura da função ou tipo, antes da chave de abertura. Em where você pode especificar que T: Comparable & Hashable (conforme a dois protocolos simultaneamente), ou que T.U == Int (concretizar um 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
    }
}

A extensão com where adiciona métodos apenas para aqueles tipos que satisfazem a condição. Container obterá o método isSorted, enquanto Container não, porque Any não é Comparable. Este é um poderoso mecanismo de funcionalidade condicional.

Associated Types em Protocolos

Associated Types (tipos associados) — são uma forma de tornar um protocolo genérico sem especificar um tipo concreto no estágio de declaração. Em vez de , o protocolo declara um associatedtype, que é concretizado na implementação. Isso é especialmente importante para coleções: o protocolo Sequence não sabe quais elementos a sequência conterá.

Vinculando Associated Types via where

Usando where você pode estabelecer relações entre associated types de diferentes protocolos. Por exemplo, você pode exigir que o Item de um protocolo corresponda ao Iterator.Element de outro. Isso garante compatibilidade de tipo no nível do compilador.

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 concretiza Element como Int usando typealias. O compilador verifica se todos os requisitos do protocolo são atendidos com este tipo. Sem associated types, você teria que escrever StackProtocol com um protocolo genérico, mas Swift usa associated types para consistência com as pontes Objective-C e melhor legibilidade.

Generic em Extensões e Subscritos

Extensões genéricas permitem adicionar métodos a um tipo genérico com restrições adicionais. Este é o padrão de “conformidade condicional”, onde um tipo ganha funcionalidade apenas sob certas condições. Subscritos também podem ser genéricos.

Subscrito Genérico

Um subscrito pode ser genérico: ele aceita parâmetros genéricos entre colchetes angulares. Isso é útil para acesso seguro a coleções com índices arbitrários, onde o índice pode 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 construção fornece composição poderosa: o método sum aparece apenas em arrays numéricos, e o subscrito com índices arbitrários funciona com qualquer sequência de índices inteiros. O compilador gerencia a visibilidade desses membros com base nas condições where.

Erros Comuns ao Trabalhar com Genéricos

Erros ao usar genéricos geralmente estão relacionados a restrições incorretas ou à tentativa de usar genéricos onde um tipo concreto é necessário. Vamos ver três cenários comuns que os desenvolvedores enfrentam.

Parametrização Excessiva

Adicionar parâmetros genéricos onde um tipo concreto é suficiente é um antipadrão. Se uma função sempre trabalha com String, não há necessidade de torná-la . Isso complica o código sem benefício. Generics são justificados quando o tipo realmente varia, não para “flexibilidade futura” abstrata.

Falta de Restrição where

Chamar um método em um parâmetro genérico sem especificar que o método existe é um erro. não pode chamar .count se T: Collection não for especificado. Sempre adicione restrições aos parâmetros de tipo, caso contrário o compilador rejeitará o 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 }

O erro é claro: o genérico pode ser qualquer tipo, e o compilador não sabe se ele tem count. A restrição Collection resolve o problema. Da mesma forma para Equatable, Hashable, Numeric — sempre especifique o protocolo se você planeja chamar métodos ou operadores no parâmetro genérico.

Perguntas Frequentes

O que é Generic em Swift em termos simples?

Generic é uma forma de escrever código que funciona com qualquer tipo, sem duplicar a mesma lógica para Int, String e outros tipos. Em vez de um tipo concreto, um placeholder é usado, que é substituído pelo tipo real no ponto de uso.

Como Generic difere de Any?

Generic preserva informação sobre o tipo concreto em tempo de compilação, permitindo ao compilador verificar tipos e gerar código otimizado. Any é apagamento de tipo: qualquer valor pode ser passado, mas o tipo se perde, e é necessário casting (as?).

Como restringir um Generic com um protocolo?

Use a sintaxe T: SomeProtocol entre colchetes angulares ou uma cláusula separada where T: SomeProtocol. As restrições garantem que o parâmetro genérico suporta métodos e propriedades específicos.

O que é um Associated Type em um protocolo?

Associated Type (associatedtype) é um placeholder para um tipo dentro de um protocolo. O protocolo não especifica um tipo concreto, mas declara um associatedtype, que é concretizado na implementação: Array tem Element, Dictionary tem Key e Value.

Generics são mais rápidos ou mais lentos que tipos concretos?

Swift compila código genérico em versões especializadas para cada tipo concreto. Na prática, uma função genérica para Int não é mais lenta que uma função escrita à mão para Int. Não há sobrecarga de abstração.

Resumo

  • Generic — mecanismo de programação genérica com parâmetro de tipo
  • Funções e tipos com parâmetros genéricos substituem múltiplas implementações duplicadas
  • Restrições where limitam o escopo de genéricos a condições necessárias
  • Associated Types permitem que protocolos sejam genéricos sem concretização na declaração
  • Extensões com where adicionam funcionalidade apenas quando condições são atendidas
  • O compilador gera código especializado — generics não adicionam sobrecarga
  • Parametrização excessiva é um antipadrão — use generics apenas quando o tipo realmente varia

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também