Cours de programmation séquentielle

Modules

Orestis Malaspinas

Organisation du code

  • Au fur et à mesure du développement séparer son code devient important.
  • Il faut modulariser le code:
    1. Écrire des foncitons.
    2. Séparer le code en fichiers (modules).
  • Aide à organiser le code.
  • Aide à maintenir le code.
  • Permet de “cacher” le code à l’utilisateur (il n’utilisera que ce que vous voulez qu’il utilise).

Modules

Une libraire (crate)

  • On peut créer une libraire avec cargo new malibrairie --lib.
  • Ou alors en créant un fichier lib.rs “à côté” du main.rs (dans src/).
  • Pour accéder à ce qui se trouve dans la librairie on devra utiliser

    extern crate ma_librairie;
  • Et appeler les fonctions, enums, …

    ma_librairie::ma_fct();
    ma_librairie::Mon_enum;

La définition d’un module

  • Dans le fichier lib.rs on peut à présent créer un/deux/… modules contenant une fonction

    mod mon_module { // on peut même insérer d'autres modules à l'intérieur
        fn ma_fonction() {
            unimplemented!(); // macro très pratique!
        }
    }
    
    mod mon_autre_module {
        fn ma_fonction() {
            unimplemented!(); // macro très pratique!
        }
    }
  • Les fonctions mon_module::ma_fonction(), mon_autre_module::ma_fonction() auront une signification (et une fonctionalité différente).

Fichiers (1/3)

  • Avoir tous ses modules dans un fichier: pas pratique.
  • On déclare les modules dans src/lib.rs, on met le contenu dans src/mon_module.rs

    mod mon_module;
    
    mod mon_autre_module {
        fn ma_fonction() {
            unimplemented!(); // macro très pratique!
        }
    }
  • Équivalent à

    mod mon_module {
        // contenu de src/mon_module.rs
    }
    
    mod mon_autre_module {
        fn ma_fonction() {
            unimplemented!(); // macro très pratique!
        }
    }

Fichiers (2/3)

  • On peut aller encore plus loin: src/lib.rs

    mod mon_module {
        fn ma_fonction() {
            unimplemented!(); // macro très pratique!
        }
    
        mod mon_autre_module {
            fn ma_fonction() { 
                unimplemented!(); // macro très pratique!
            }
        }
    }
    
  • Peut devenir:
    • src/lib.rs

      mod mon_module;
    • src/mon_module/mod.rs

      fn ma_fonction() {
          unimplemented!(); // macro très pratique!
      }
      
      mod mon_autre_module;
    • src/mon_module/mon_autre_module.rs

      fn ma_fonction() {
          unimplemented!(); // macro très pratique!
      }

Fichiers (3/3)

  • Avec la structure de module suivante

    mod mon_module {
        fn ma_fonction() {
            unimplemented!(); // macro très pratique!
        }
    
        mod mon_autre_module {
            fn ma_fonction() { 
                unimplemented!(); // macro très pratique!
            }
        }
    }
    
  • On accède aux deux ma_fonction() avec

    mon_module::ma_fonction();
    mon_module::mon_autre_module::ma_fonction();

Visibilité

Modules (1/4)

  • Structure fichiers:

  • src/lib.rs

    mod mon_module;
  • src/mon_module/mod.rs

    fn ma_fonction() {
        unimplemented!(); // macro très pratique!
    }
  • src/main.rs

    extern crate ma_librairie;
    
    fn main() {
        ma_librarie::mon_module::ma_fonction();
    }

Modules (2/4)

  • Par défaut les modules sont privés.
$ cargo build
   Compiling ma_librairie v0.1.0 ($PATH/ma_librairie)

error[E0603]: module `mon_module` is private
 --> src/main.rs:4:2
  |
4 |     ma_librairie::mon_module::ma_fonction();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0603`.
error: Could not compile `ma_librairie`.

To learn more, run the command again with --verbose.

Modules (3/4)

  • On contrôle la visibilité des modules avec pub.

  • On a joute pub mon module dans src/lib.rs

    pub mod mon_module;
  • Par défaut les fonctions sont privées.

    $ cargo build
       Compiling ma_librairie v0.1.0 ($PATH/ma_librairie)                                                                                                                                    
    error[E0603]: function `ma_fonction` is private
     --> src/main.rs:4:2
      |
    4 |     ma_librairie::mon_module::ma_fonction();
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0603`.
    error: Could not compile `ma_librairie`.
    
    To learn more, run the command again with --verbose.

Modules (4/4)

  • On a joute pub fn ma_fonction() dans src/mon_module.rs

       Compiling ma_librairie v0.1.0 ($PATH/ma_librairie)                                                                                                                                    
        Finished dev [unoptimized + debuginfo] target(s) in 1.28s
  • Quand plusieurs modules sont imbriqués, les appels sont longs: ma_librarie::mon_module::ma_fonction();

  • Avec use, on peut se simplifier la vie src/main.rs

    extern crate ma_librairie;
    
    use ma_librairie::mon_module::ma_fonction;
    
    fn main() {
        ma_fonction();
    }
  • Ou encore avec * on peut rendre visible tout le module

    extern crate ma_librairie;
    
    use ma_librairie::mon_module::*;
    
    fn main() {
        ma_fonction();
    }

Résumé

  • Les modules permettent de compartimenter le code.
  • Par défaut tout ce qui se trouve dans un module est privé.
  • On contrôle la visibilité avec pub
  • Si un item est public il peut être accédé depuis n’importe quel module parent.
  • Si un item est privé il n’est accessible que depuis son parent direct et n’importe lequel de ses modules enfants.
  • On peut rendre visible des sous-modules, ou des items avec use.