ProgrammationDéveloppeur Backend

Comment Rust gère-t-il les modificateurs de visibilité (pub, pub(crate), pub(super)) et en quoi diffèrent-ils des modificateurs dans d'autres langages ? Quels problèmes peuvent survenir en cas de mauvaise configuration de la visibilité des éléments du module ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Dans Rust, les modificateurs de visibilité contrôlent l'accès aux éléments des modules (structures, fonctions, constantes, etc.). Par défaut, tout ce qui est déclaré dans un module est privé (accessible uniquement dans ce module). Il existe des modificateurs spéciaux :

  • pub : rend l'élément accessible publiquement (visible depuis n'importe quel module externe).
  • pub(crate) : la visibilité est limitée au crate (paquet) actuel.
  • pub(super) : la visibilité est limitée au module parent.
  • pub(in path) : la visibilité est limitée à un chemin spécifique.

Exemple :

mod foo { pub struct Bar { pub x: i32, // champ accessible partout y: i32, // champ privé } pub(crate) fn crate_fn() {} pub(super) fn super_fn() {} fn private_fn() {} }

La principale différence par rapport à, par exemple, C++ ou Java, est qu'il n'y a pas de niveau distinct pour « protected », et que l'accessibilité est strictement contrôlée au niveau des modules/chemins, plutôt qu'à travers la hiérarchie des classes.

Question piège.

Question : Si une structure est déclarée comme pub struct Foo, ses champs privés seront-ils accessibles dans un autre module du même projet ?

Réponse fréquente : Oui, car la structure est publique.

Réponse correcte : Non, seule la structure elle-même (Foo) deviendra visible, et ses champs ne le seront que s'ils sont également déclarés avec le modificateur pub. Les champs sans pub restent privés, même si la structure elle-même est publique.

Exemple :

mod foo { pub struct Bar { pub x: i32, y: i32, } } fn main() { let bar = foo::Bar { x: 1, y: 2 }; // Erreur : champ `y` inaccessible }

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


Histoire

Dans un grand projet, on a publiquement exporté une structure via pub, mais les champs ont été laissés privés par défaut. D'autres modules ne pouvaient pas créer d'instances de la structure directement, et la seule solution était d'écrire des constructeurs supplémentaires ou de déclarer les champs nécessaires comme pub. Cela a conduit à un échec de l'API jusqu'à sa révision finale.


Histoire

Un des développeurs d'une bibliothèque a utilisé uniquement pub(crate) pour les fonctions, présumant qu'elles pouvaient être appelées depuis des projets binaires utilisant cette bibliothèque. Cependant, ces fonctions sont devenues inaccessibles dans un crate binaire externe, ce qui a causé des problèmes d'intégration.


Histoire

Dans un des plugins pour serveurs API, pub(super) a été utilisé pour des structures, mais après un certain temps, il est devenu nécessaire d'y accéder depuis d'autres modules ; à cause de la configuration de la visibilité, il a fallu réécrire radicalement plusieurs modules pour assurer la portée nécessaire sans compromettre l'encapsulation.