Historique de la question :
En Swift jusqu'à la version 5, lors du retour d'une valeur correspondant à un protocole avec associated type, on se heurtait souvent à des limitations — le type ne pouvait pas être utilisé directement comme type de retour, une érasion de type était nécessaire. Pour améliorer la lisibilité et les performances, les types opaques ont été introduits — des valeurs de retour via le mot-clé some, permettant de décrire des abstractions dans les interfaces publiques.
Problème :
Quand il faut cacher le type réel de la valeur de retour, tout en conservant une abstraction via un protocole, mais éviter les coûts de dispatch dynamique et d'érosion de type. Par exemple, en retournant des collections, des séquences, des composants de vue.
Solution :
Les types opaques permettent de retourner un type conforme à un protocole, en cachant son implémentation concrète. Le compilateur connaît le type réel, mais la partie appelante ne le connaît pas.
Exemple :
protocol Shape { func area() -> Double } struct Circle: Shape { var radius: Double func area() -> Double { Double.pi * radius * radius } } func makeCircle() -> some Shape { return Circle(radius: 3) } let s = makeCircle() print(s.area()) // fonctionne
Caractéristiques clés :
someEn quoi un type opaque (some Protocol) diffère-t-il d'un type de retour Protocol ?
Le type opaque a une implémentation concrète lors de la compilation (bien qu'elle soit cachée de l'extérieur). Lors du retour d'un Protocol, le dispatch dynamique est utilisé, il n'y a pas de sécurité de type s'il y a un associated type.
Peut-on retourner des types différents en utilisant some Protocol dans une seule fonction ?
Non. Tous les retours doivent retourner le même type réel :
func maker(flag: Bool) -> some Shape { if flag { return Circle(radius: 3) } else { return Square(size: 2) // Erreur : le type de retour ne correspond pas } }
Un associatedtype dans un Protocole peut-il être utilisé via some Protocol ?
Oui. C'est précisément pour cela (avant tout) qu'un type opaque est nécessaire :
protocol View { associatedtype Body } func makeView() -> some View { /* ... */ }
Une fonction retourne un protocole sans opaque, ne permettant pas d'utiliser des méthodes avec associatedtype, nécessitant une érosion de type complexe, le code ne compile pas ou fonctionne de manière non optimale.
Avantages :
Inconvénients :
ViewBuilder dans SwiftUI utilise some View, cachant les détails, augmentant la sécurité des types, améliorant la vitesse de compilation et d'exécution.
Avantages :
Inconvénients :