Generics en Swift pour les débutants : pourquoi en avez-vous besoin et comment les utiliser

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi ne peut-on pas se passer des Generics en Swift ?

Imaginez que vous deviez écrire une fonction qui additionne deux nombres. Ensuite, une fonction pour additionner deux chaînes de caractères. Puis, pour des tableaux. Sans la programmation générique (Generics), vous seriez obligé de créer une version distincte du code pour chaque type de données. Cela augmente non seulement la taille du code, mais complique également sa maintenance.

Les Generics (génériques) en Swift sont un outil puissant qui permet d'écrire un code flexible, réutilisable et type-safe. Ils sont le fondement de structures populaires comme Array, Dictionary et Optional. Dans cet article, nous allons voir pourquoi les Generics sont nécessaires, comment les utiliser en pratique et pourquoi tout développeur iOS/macOS débutant doit maîtriser ce sujet.



Que sont les Generics en termes simples ?

Generics (généralisations) sont une façon d'écrire du code qui fonctionne avec n'importe quel type de données, sans sacrifier le typage strict de Swift. Au lieu de spécifier un type concret (par exemple, Int ou String), vous utilisez un placeholder (le plus souvent la lettre T), qui est remplacé par le type réel lors de l'appel de la fonction ou de la création de la structure.



Le problème sans Generics

Supposons que vous écriviez une fonction pour échanger les valeurs de deux variables. Sans Generics, vous devriez écrire ceci :

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}

C'est une duplication évidente. Si vous devez échanger des Double ou des types personnalisés, le nombre de fonctions augmentera.



La solution avec Generics

Une seule fonction universelle remplacera toutes les précédentes :

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

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

var firstName = "Anna"var lastName = "Ivanova"swapValues(&firstName, &lastName) // firstName = "Ivanova"

Les chevrons <T> déclarent le placeholder de type. Le compilateur détermine automatiquement que T est Int dans le premier cas et String dans le second. Le code devient concis et sûr.



Comment utiliser les Generics : scénarios principaux

Les Generics en Swift sont utilisés dans les fonctions, les structures, les classes, les énumérations et les protocoles. Examinons les cas les plus courants.



1. Fonctions génériques

Nous avons déjà vu l'exemple avec swapValues. Mais on peut aller plus loin — créer une fonction qui trouve l'index d'un élément dans un tableau :

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("Index : \\(index)") // Index : 2}

Notez le <T: Equatable>. C'est une contrainte de type (type constraint). Nous disons : « T doit se conformer au protocole Equatable pour que nous puissions utiliser l'opérateur == ». Sans cette contrainte, le code ne compilerait pas.



2. Types génériques (structures et classes)

Créons une structure simple « Pile » (LIFO) qui peut stocker n'importe quel type :

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 }}

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

Blogs

Book Recommendations