Generics em Swift: para que servem e como usar

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course
```html

Introdução: o que são Generics e por que são importantes em Swift



Generics (tipos genéricos) — uma das capacidades mais poderosas e elegantes da linguagem Swift. Eles permitem escrever código flexível e reutilizável que funciona com qualquer tipo de dado, mantendo ao mesmo tempo a tipagem estrita. Se você já usou Array<Int>, Dictionary<String, Any> ou Optional<T> — você já encontrou Generics.



Neste artigo, vamos analisar para que servem os Generics em Swift, como funcionam na prática e mostrar exemplos para desenvolvimento iOS/macOS. O material será útil tanto para iniciantes quanto para desenvolvedores experientes que desejam estruturar seus conhecimentos.



1. Para que servem os Generics em Swift?



O objetivo principal dos Generics é evitar duplicação de código e aumentar sua segurança. Imagine que você precisa escrever uma função que troque dois valores. Sem Generics, você teria que criar funções separadas para Int, String, Double e assim por diante:



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}


Com Generics, esta tarefa é resolvida com uma única função universal:



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

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

var name1 = "Alice", name2 = "Bob"swapValues(&name1, &name2) // name1 = "Bob", name2 = "Alice"


Vantagens dos Generics:

  • Reutilização de código: uma função/tipo funciona com qualquer tipo de dado.
  • Type safety: o compilador verifica os tipos em tempo de compilação, eliminando erros de execução.
  • Desempenho: Generics em Swift são implementados através de polimorfismo em tempo de compilação (especialização), portanto não há custos adicionais de casting de tipos.
  • Legibilidade: o código se torna mais abstrato e conciso.


2. Funções Genéricas: sintaxe e exemplos



Uma função genérica é declarada usando colchetes angulares <T>, onde T é um placeholder para o tipo. Você pode usar qualquer identificador: T, Element, Value, etc.



Exemplo básico: encontrar o índice de um elemento



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

let numbers = [1, 3, 5, 7, 9]if let index = findIndex(of: 5, in: numbers) { print("Índice do número 5: \\(index)") // Índice do número 5: 2}


Observe a restrição <T: Equatable>. Isto é um type constraint. Ele diz ao compilador: "T deve estar em conformidade com o protocolo Equatable". Sem esta restrição, o operador == não estaria disponível.



Múltiplos parâmetros de tipo



Você pode usar vários parâmetros de tipo:



func combine<T, U>(_ first: T, with second: U) -> String {    return "\\(first) + \\(second)"}

let result = combine(42, with: "resposta")print(result) // 42 + resposta


3. Tipos Genéricos: criação de structs e classes genéricas



Generics não se aplicam apenas a funções, mas também a tipos. O exemplo mais popular é Array<Element>. Vamos criar nossa própria struct genérica — uma pilha (LIFO):



struct Stack<Element> {    private var items: [Element] = []        mutating func push(_ item: Element) {        items.append(item
```                

Blogs

Book Recommendations