Suddividere il codice in moduli

Completato

Oltre a ottimizzare l'organizzazione del codice, i moduli forniscono anche le garanzie di privacy per valori, tipi e metodi.

Si osservi questo esempio, in cui viene modellata un'API di autenticazione semplificata:

mod authentication {
    pub struct User {
        username: String,
        password_hash: u64,
    }

    impl User {
        pub fn new(username: &str, password: &str) -> User {
            User {
                username: username.to_string(),
                password_hash: hash_password(password),
            }
        }    
    }
    fn hash_password(input: &str) -> u64 { /*...*/ }
}

fn main() {

    let user = authentication::User::new("jeremy", "super-secret");

    println!("The username is: {}", user.username);
    println!("The password is: {}", user.password_hash);

}

Nel codice riportato sopra si può vedere che il modulo authentication fornisce lo struct User con il metodo User::new, poiché sono entrambi pubblici. Si noti la parola chiave pub.

Questo codice non viene compilato perché tenta di accedere ai campi username e password_hash dallo struct User, ma questi campi sono privati. L'esecuzione del codice genera l'errore seguente:

    error[E0616]: field `username` of struct `User` is private
      --> src/main.rs:28:42
       |
    28 |     println!("The username is: {}", user.username);
       |                                          ^^^^^^^^ private field

    error[E0616]: field `password_hash` of struct `User` is private
      --> src/main.rs:29:42
       |
    29 |     println!("The password is: {}", user.password_hash);
       |                                          ^^^^^^^^^^^^^ private field

    error: aborting due to 2 previous errors

Queste informazioni sull'errore sono utili per controllare quali parti del programma possono accedere a ogni parte di un modulo specifico. Se si vuole concedere l'accesso in lettura al campo username e l'accesso in scrittura al campo password mantenendoli però privati, è possibile usare i metodi getter e setter:

mod authentication {

    // ...

    impl User {

    // ...

        pub fn get_username(&self) -> &String {
            &self.username
        }
    
        pub fn set_password(&mut self, new_password: &str) {
            self.password_hash = hash_password(new_password)
        }
    }
}

A questo punto ogni tentativo di lettura e scrittura sarà controllato dal modulo authentication.

Per visualizzare il codice per questa unità, visitare questo collegamento a Rust Playground.