Protocol en Swift est un contrat qui définit un ensemble d’exigences que tout type adoptant doit satisfaire. Les protocoles sont le fondement de la programmation orientée protocole (POP) — un paradigme recommandé par Apple pour Swift aux côtés de la POO classique. Selon la Apple Documentation, 2026, les structures, classes et énumérations peuvent adopter des protocoles, rendant l’architecture flexible et testable.
Points clés
Protocol est une interface abstraite qui définit ce qu’un type doit être capable de faire, mais pas comment il le fait. En Swift, un protocole est analogue aux interfaces en Java ou Go, mais avec des capacités supplémentaires.
Un protocole peut exiger :
{ get } ou { get set }Selon la WWDC 2015, Apple a introduit la programmation orientée protocole comme approche fondamentale de l’architecture des applications Swift. Contrairement à la POO, où l’héritage de classes crée des hiérarchies rigides, la POP offre la composition de protocoles. Cela offre de la flexibilité : un seul type peut se conformer à plusieurs protocoles, obtenant leurs exigences et implémentations via des extensions.
Protocol se déclare avec le mot-clé protocol, un nom et un corps.
protocol Drawable {
func draw(context: CGContext)
var boundingBox: CGRect { get }
}
Un type adopte un protocole en utilisant deux-points après son nom :
struct Circle: Drawable {
let center: CGPoint
let radius: CGFloat
func draw(context: CGContext) {
context.addArc(center: center, radius: radius, ...)
}
var boundingBox: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
}
Un seul type peut adopter plusieurs protocoles séparés par des virgules : struct MyType: ProtocolA, ProtocolB. Le compilateur vérifie que toutes les exigences de chaque protocole sont remplies.
Les exigences de propriétés sont déclarées avec le mot-clé var et les spécificateurs d’accès { get } ou { get set }.
protocol UserProtocol {
var name: String { get }
var age: Int { get set }
static var maxAge: Int { get }
mutating func updateName(_ newName: String)
}
Le mot-clé mutating dans un protocole indique que la méthode peut modifier self. Les structures doivent implémenter une telle méthode comme mutating, tandis que les classes peuvent l’omettre. Les exigences de méthodes sont déclarées avec une signature complète, y compris les étiquettes de paramètres.
Protocol peut hériter d’un autre protocole, ajoutant de nouvelles exigences. Cela crée une hiérarchie de contrats sans couplage rigide aux classes.
protocol Vehicle {
var speed: Double { get set }
func move()
}
protocol Flyable: Vehicle {
var altitude: Double { get set }
func takeOff()
}
Un type adoptant Flyable doit remplir les exigences des deux protocoles — Vehicle et Flyable. Swift supporte l’héritage multiple de protocoles : protocol A: B, C.
Protocol Composition est un mécanisme qui permet de spécifier qu’un type doit se conformer à plusieurs protocoles simultanément, sans créer un nouveau protocole combiné.
func render(_ item: Drawable & Animatable) {
item.draw(context: ...)
item.animate(duration: 0.3)
}
La composition (&) fonctionne dans les paramètres de fonctions, les variables et les contraintes génériques. Le compilateur vérifie que le type passé simultanément satisfait tous les protocoles. La composition est largement utilisée dans SwiftUI : some View est un générique avec composition.
Protocol Composition est préférable à la création d’une hiérarchie d’héritage : au lieu de protocol A: B, C, on peut adopter directement B & C. Cela offre de la flexibilité et réduit le couplage. La composition est particulièrement utile dans les paramètres de fonctions et les contraintes génériques où l’on doit combiner temporairement des exigences sans créer un protocole intermédiaire. Cela réduit le nombre de types auxiliaires dans le code.
Protocol peut être utilisé comme type d’une variable, paramètre de fonction ou élément de collection. C’est ce qu’on appelle un type existentiel.
var drawableItem: Drawable
let items: [Drawable] = [Circle(...), Rectangle(...)]
func process(drawables: [any Drawable]) {
for item in drawables {
item.draw(context: ...)
}
}
Le mot-clé any (Swift 5.6+) marque explicitement un existentiel. Sans any, le compilateur émet un avertissement. Swift supporte également some (types opaques) pour cacher le type concret derrière un protocole — c’est une approche standard dans SwiftUI.
En travaillant avec les protocoles, les développeurs commettent souvent plusieurs erreurs récurrentes.
Drawable au lieu de <T: Drawable> là où un type concret est nécessaireAnyObject inutilement, ce qui exclut struct et enumFoire aux questions
Protocol définit uniquement des exigences sans implémentation (jusqu’aux protocol extensions). Une abstract class peut contenir implémentation et état. Swift n’a pas de classes abstraites — leur rôle est assuré par les protocoles avec extensions.
Oui, les structures, classes et énumérations peuvent toutes adopter des protocoles. C’est le fondement de la POP : vous n’êtes pas obligé d’utiliser des classes pour organiser l’architecture. Les structures avec protocoles offrent la sémantique de valeur et l’immuabilité.
Type associé (associatedtype) est un espace réservé pour un type que le type implémentant détermine lui-même. Exemple : Collection a associatedtype Element. C’est un générique au niveau du protocole.
Oui, ajoutez l’héritage de AnyObject : protocol MyProtocol: AnyObject. Alors seules les classes pourront adopter ce protocole. C’est utile pour les références faibles et les délégations.
Utilisez is pour vérifier et as? pour caster : if let drawable = item as? Drawable. Cela ne fonctionne que pour les protocoles sans types associés.
Résumé
&) combine des protocoles sans héritageany) et types opaques (some) — deux façons de travailler avec les protocolesNous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi