Ricerca…


Sintassi

  • mod modname ; // Cerca il modulo in modname .rs o modname /mod.rs nella stessa directory
  • mod modname { block }

Albero dei moduli

File:

- example.rs (root of our modules tree, generally named lib.rs or main.rs when using Cargo)
- first.rs
- second/
  - mod.rs
  - sub.rs

moduli:

- example        -> example
  - first        -> example::first
  - second       -> example::second
    - sub        -> example::second::sub
  - third        -> example::third

example.rs

pub mod first;
pub mod second;
pub mod third {
    ...
}

Il second modulo deve essere dichiarato nel file example.rs il suo genitore è un example e non, per esempio, first e quindi non può essere dichiarato nel first.rs o in un altro file nello stesso livello di directory

second/mod.rs

pub mod sub;

L'attributo # [path]

L'attributo #[path] Rust può essere usato per specificare il percorso per cercare un particolare modulo se non si trova nella posizione standard. Questo è in genere scoraggiato , tuttavia, perché rende la gerarchia del modulo fragile e rende facile interrompere la build spostando un file in una directory completamente diversa.

#[path="../path/to/module.rs"]
mod module;

Nomi in codice vs nomi in `use`

La sintassi dei due punti dei nomi nell'istruzione use sembra simile ai nomi usati altrove nel codice, ma il significato di questi percorsi è diverso.

I nomi nell'istruzione use di default sono interpretati come assoluti, a partire dalla radice del crate. I nomi altrove nel codice sono relativi al modulo corrente.

La dichiarazione:

use std::fs::File;

ha lo stesso significato nel file principale della cassa e nei moduli. D'altra parte, un nome di funzione come std::fs::File::open() farà riferimento alla libreria standard di Rust solo nel file principale della cassa, poiché i nomi nel codice vengono interpretati in relazione al modulo corrente.

fn main() {
    std::fs::File::open("example"); // OK
}

mod my_module {
   fn my_fn() {
       // Error! It means my_module::std::fs::File::open()
       std::fs::File::open("example"); 

       // OK. `::` prefix makes it absolute 
       ::std::fs::File::open("example"); 

       // OK. `super::` reaches out to the parent module, where `std` is present
       super::std::fs::File::open("example"); 
   } 
}

Per far sì che i nomi std::… comportino ovunque come nella radice della cassa, è possibile aggiungere:

use std;

Al contrario, puoi use percorsi relativi anteponendoli a parole chiave self o super :

 use self::my_module::my_fn;

Accesso al modulo genitore

A volte, può essere utile importare le funzioni e le strutture relativamente senza dover use qualcosa con il suo percorso assoluto nel progetto. Per ottenere ciò, puoi usare il modulo super , in questo modo:

fn x() -> u8 {
    5
}

mod example {
    use super::x;

    fn foo() {
        println!("{}", x());
    }
}

È possibile utilizzare super più volte per raggiungere il 'nonno' del modulo corrente, ma si dovrebbe stare attenti a introdurre problemi di leggibilità se si utilizza super troppe volte in una sola importazione.

Esportazioni e visibilità

Struttura della directory:

yourproject/
    Cargo.lock
    Cargo.toml
    src/
        main.rs
        writer.rs

main.rs

// This is import from writer.rs
mod writer;

fn main() {
    // Call of imported write() function.
    writer::write()
    
    // BAD
    writer::open_file()
}

writer.rs

// This function WILL be exported.
pub fn write() {}

// This will NOT be exported.
fn open_file() {}

Organizzazione del codice di base

Vediamo come possiamo organizzare il codice, quando il codebase sta diventando più grande.

01. Funzioni

fn main() {
  greet();
}

fn greet() {
  println!("Hello, world!");
}

02. Moduli - Nello stesso file

fn main() {
  greet::hello();
}

mod greet {
  // By default, everything inside a module is private
  pub fn hello() { // So function has to be public to access from outside
    println!("Hello, world!");
  }
}

03. Moduli - In un file diverso nella stessa directory

Quando sposti del codice in un nuovo file, non è necessario avvolgere il codice in una dichiarazione mod . Il file stesso funge da modulo.

// ↳ main.rs
mod greet; // import greet module

fn main() {
  greet::hello();
}
// ↳ greet.rs
pub fn hello() { // function has to be public to access from outside
  println!("Hello, world!");
}

Quando si sposta un codice in un nuovo file, se tale codice è stato spostato da una dichiarazione mod , questo sarà un sottomodulo del file.

// ↳ main.rs
mod greet;

fn main() {
  greet::hello::greet();
}
// ↳ greet.rs
pub mod hello { // module has to be public to access from outside
  pub fn greet() { // function has to be public to access from outside
    println!("Hello, world!");
  }
}

04. Moduli - In un file diverso in una directory diversa

Quando si sposta un codice in un nuovo file in una directory diversa, la stessa directory funge da modulo. E mod.rs nella root del modulo è il punto di ingresso al modulo directory. Tutti gli altri file in quella directory agiscono come un sottomodulo di quella directory.

// ↳ main.rs
mod greet;

fn main() {
  greet::hello();
}
// ↳ greet/mod.rs
pub fn hello() {
  println!("Hello, world!");
}

Quando hai più file nella root del modulo,

// ↳ main.rs
mod greet;

fn main() {
  greet::hello_greet()
}
// ↳ greet/mod.rs
mod hello;

pub fn hello_greet() {
  hello::greet()
}
// ↳ greet/hello.rs
pub fn greet() {
  println!("Hello, world!");
}

05. Moduli - Con self

fn main() {
  greet::call_hello();
}

mod greet {
  pub fn call_hello() { 
    self::hello();
  }

  fn hello() {
    println!("Hello, world!");
  }
}

06. Moduli - Con super

  1. Quando si desidera accedere a una funzione root dall'interno di un modulo,
fn main() {
  dash::call_hello();
}

fn hello() {
  println!("Hello, world!");
}

mod dash {
  pub fn call_hello() {
    super::hello();
  }
}
  1. Quando si desidera accedere a una funzione nel modulo esterno / genitore dall'interno di un modulo nidificato,
fn main() {
  outer::inner::call_hello();
}

mod outer {

  pub fn hello() {
    println!("Hello, world!");
  }

  mod inner {
    pub fn call_hello() {
      super::hello();
    }
  }

}

07. Moduli - Con l' use

  1. Quando vuoi associare il percorso completo a un nuovo nome,
use greet::hello::greet as greet_hello;

fn main() {
  greet_hello();
}

mod greet {
  pub mod hello {
    pub fn greet() {
      println!("Hello, world!");
    }
  }
}
  1. Quando si desidera utilizzare il contenuto del livello di ambito della cassa
fn main() {
  user::hello();
}

mod greet {
  pub mod hello {
    pub fn greet() {
      println!("Hello, world!");
    }
  }
}

mod user {
  use greet::hello::greet as call_hello;

  pub fn hello() {
    call_hello();
  }
}


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow