ProgrammationDéveloppeur iOS

Expliquez le principe de fonctionnement de l'accès à private/protected/internal/public/open en Swift. Quand est-il préférable d'utiliser chaque modificateur et avec quelles erreurs peut-on être confronté dans un projet réel ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

En Swift, il existe cinq niveaux d'accès pour les membres des types (propriétés, méthodes, etc.) et pour les types eux-mêmes :

  • open — le niveau de publicité maximale. Peut être hérité et redéfini même en dehors du module.
  • public — accessible en dehors du module, mais ne peut pas être redéfini/hérité.
  • internal (par défaut) — accessible à l'intérieur du module.
  • fileprivate — accessible uniquement dans le fichier.
  • private — accessible uniquement dans la portée de la déclaration (l'extension est également dans cette portée).

Règles d'utilisation :

  • Utilisez private pour la logique qui ne doit pas être visible en dehors de la déclaration.
  • fileprivate — si vous devez échanger des données dans un même fichier (par exemple, entre deux extensions liées).
  • internal — par défaut pour tout ce qui est public dans le module.
  • public/open — pour les API utilisées par d'autres modules/frameworks.

Exemple :

open class MyOpenClass {} public class MyPublicClass {} internal class InternalClass {} fileprivate class FilePrivateClass {} private class PrivateClass {}

Question piège

Quelle est la différence entre open et public lors de la description d'une classe ? Pourquoi tous les classes publiques ne sont-elles pas disponibles pour l'héritage ?

Réponse : open marque une classe/méthode comme étant disponible pour la redéfinition et l'héritage en dehors de son module. public ouvre seulement l'accès à l'utilisation, mais ne permet pas de créer des héritiers en dehors du module. D'une part, cela protège l'implémentation contre les modifications indésirables, d'autre part, ça ouvre seulement les points d'extension nécessaires.

public class PublicClass {} open class OpenClass {} // Dans un autre module : class InheritFromOpen: OpenClass {} // OK class InheritFromPublic: PublicClass {} // Erreur !

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Dans une bibliothèque générale, une classe a été marquée comme public, et un projet externe a tenté de l'étendre en redéfinissant les méthodes. Le projet ne compilait pas à cause d'une mauvaise compréhension de la différence entre public et open — cela a coûté à l'équipe une semaine supplémentaire pour peaufiner l'interface.


Histoire

À l'intérieur d'un fichier, on a essayé d'accéder à une propriété privée depuis une extension — mais la propriété avait été déclarée non pas comme fileprivate, mais comme private. Cela a conduit à une erreur de compilation qui n'a été remarquée qu'à la construction d'intégration.


Histoire

Dans une application avec plusieurs frameworks tous les types étaient marqués comme internal (par défaut). Quand il a fallu utiliser les types entre les modules, l'interface n'était pas disponible — il a fallu réécrire des dizaines de déclarations en public, ce qui a pris du temps supplémentaire et des tests.