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
- 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();
}
}
- 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
- 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!");
}
}
}
- 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();
}
}