Que cache le mot-clé open en Swift ? Analyse pour débutants
Avez-vous déjà écrit une classe en Swift, ajouté public, puis essayé d'en hériter dans un autre module — et obtenu une erreur de compilation ? Si oui, vous n'êtes pas seul. Cette question est l'une des plus populaires sur Stack Overflow parmi les développeurs Swift débutants. Des milliers de personnes trébuchent sur la même pierre : le mot-clé open.
Dans cet article, nous allons une fois pour toutes comprendre ce qu'est open en Swift, en quoi il diffère de public, quand l'utiliser et quand il ne faut absolument pas l'utiliser. Nous écrirons du code réel, examinerons les erreurs et apprendrons à les corriger. C'est parti !
Système de modificateurs d'accès en Swift : petit rappel
Avant de plonger dans open, rappelons quels sont les niveaux d'accès en Swift. Il y en a cinq (du plus restrictif au plus ouvert) :
private— accessible uniquement à l'intérieur d'un seul fichier et d'une seule déclaration (par exemple, à l'intérieur d'une classe).fileprivate— accessible dans tout le fichier.internal— accessible dans tout le module (c'est le niveau par défaut).public— accessible depuis d'autres modules, mais on ne peut pas hériter ni redéfinir.open— accessible depuis d'autres modules, on peut hériter et redéfinir.
Le principal mystère réside dans la différence entre public et open. À première vue, ils se ressemblent : tous deux permettent d'accéder à une classe, une méthode ou une propriété depuis un autre module. Mais il y a une différence fondamentale que nous allons maintenant analyser avec des exemples.
Exemple : une classe public qui ne peut pas être étendue
Imaginez que vous écrivez une bibliothèque (framework) pour travailler avec le réseau. Vous créez une classe NetworkService et la déclarez public :
// Module : MyNetworkingFrameworkpublic class NetworkService { public func fetchData() { print("Fetching data from network...") }}Maintenant, un autre développeur intègre votre framework et veut créer sa propre classe améliorée basée sur celle-ci :
// Module : MyAppimport MyNetworkingFramework
// Erreur ! Cannot inherit from a public classclass MyNetworkService: NetworkService { override func fetchData() { print("My custom fetching...") }}Le compilateur générera une erreur. Pourquoi ? Parce que public est un accès en lecture seule depuis un autre module. Vous pouvez utiliser une instance de la classe, appeler ses méthodes, mais vous ne pouvez pas en hériter. Cela a été fait intentionnellement : l'auteur de la bibliothèque veut contrôler quelles classes peuvent être étendues et lesquelles ne le peuvent pas.
Solution : utiliser open
Si l'auteur de la bibliothèque veut autoriser l'héritage, il doit explicitement indiquer open :
// Module : MyNetworkingFrameworkopen class NetworkService { open func fetchData() { print("Fetching data from network...") }}Maintenant, dans un autre module, on peut tranquillement hériter et redéfinir les méthodes :
// Module : MyAppimport MyNetworkingFramework
class MyNetworkService: NetworkService { override func fetchData() { print("My custom fetching with extra logging...") super.fetchData() }}Voilà toute la magie. Le mot-clé open est une autorisation d'héritage et de redéfinition en dehors du module.
Pourquoi open est-il important pour l'architecture ?
Les développeurs de Swift et d'Apple n'ont pas introduit cette distinction pour rien. Elle aide à concevoir des API stables et sécurisées. Imaginez que vous publiez une bibliothèque et que toutes ses classes soient open.