Ce face module și vizibilitate (mod, pub, crate, super)
Un crate este unitatea de compilare: un program (cu main.rs) sau o bibliotecă (cu lib.rs). În interior, codul se organizează în module cu mod. Un modul poate fi scris în același fișier (mod plati { ... }) sau într-un fișier separat: mod plati; în main.rs încarcă src/plati.rs (sau src/plati/mod.rs).
Totul este privat implicit: funcțiile, structurile, câmpurile lor și sub-modulele se văd doar în modulul lor și în copiii lui. pub le face vizibile pentru exterior; pub(crate) le face vizibile în tot crate-ul, dar nu și pentru cine folosește biblioteca. La o structură pub, fiecare câmp are nevoie de propriul pub; la un enum pub, toate variantele sunt publice.
Căile se scriu cu ::. crate:: pornește de la rădăcina crate-ului (cale absolută), super:: urcă în modulul părinte, self:: înseamnă modulul curent. Ca să nu scrii căi lungi, aduci numele în domeniu cu use.
Exemple
Exemplul 1: Module, pub și căi
magazin::plati::total_cu_tva este publică, deci main o poate apela. cota_tva este privată, dar poate fi folosită de copilul ei, plati, prin super::. Produs are câmpul pret public și câmpul cod_intern privat, deci se construiește doar prin Produs::new.
mod magazin {
fn cota_tva() -> f64 {
0.21
}
pub struct Produs {
pub nume: String,
pub pret: f64,
cod_intern: u32,
}
impl Produs {
pub fn new(nume: &str, pret: f64) -> Self {
Produs { nume: nume.to_string(), pret, cod_intern: 1000 + nume.len() as u32 }
}
pub fn eticheta(&self) -> String {
format!("#{} {}", self.cod_intern, self.nume)
}
}
pub mod plati {
use super::Produs;
pub fn total_cu_tva(produse: &[Produs]) -> f64 {
let total: f64 = produse.iter().map(|p| p.pret).sum();
total * (1.0 + super::cota_tva())
}
}
}
fn main() {
let cos = vec![magazin::Produs::new("caiet", 8.0), magazin::Produs::new("pix", 2.0)];
for p in &cos {
println!("{}: {} lei", p.eticheta(), p.pret);
}
println!("Total cu TVA: {:.2} lei", crate::magazin::plati::total_cu_tva(&cos));
}
Rezultat
#1005 caiet: 8 lei
#1003 pix: 2 lei
Total cu TVA: 12.10 lei
Exemplul 2: Eroarea E0603: funcție privată
cota_tva nu are pub, deci nu poate fi apelată din main, care este în afara modulului magazin. Compilatorul arată unde este definită.
mod magazin {
fn cota_tva() -> f64 {
0.21
}
pub fn pret_final(pret: f64) -> f64 {
pret * (1.0 + cota_tva())
}
}
fn main() {
println!("{}", magazin::pret_final(100.0));
println!("{}", magazin::cota_tva());
}
Mesajul compilatorului (programul nu se compilează)
error[E0603]: function `cota_tva` is private
--> main.rs:13:29
|
13 | println!("{}", magazin::cota_tva());
| ^^^^^^^^ private function
|
note: the function `cota_tva` is defined here
--> main.rs:2:5
|
2 | fn cota_tva() -> f64 {
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0603`.
Exemplul 3: Module în fișiere separate
Structura unui proiect Cargo cu module în fișiere. mod plati; din main.rs încarcă src/plati.rs; mod card; din plati.rs încarcă src/plati/card.rs.
src/
├── main.rs // mod plati; ... plati::card::autorizeaza(120)
├── plati.rs // pub mod card; pub fn total(...) { ... }
└── plati/
└── card.rs // pub fn autorizeaza(suma: u32) -> bool { ... }
$ cargo run
Rezultat în terminal
Compiling magazin v0.1.0 (/home/ana/proiecte/magazin)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/magazin`
Plată de 120 lei autorizată
Greșeli frecvente
- Creezi fișierul
src/plati.rsdar uițimod plati;înmain.rs. Fișierul este ignorat complet: Rust nu descoperă module după numele fișierelor. - Pui
pubpe structură, dar nu și pe câmpuri: în afara modulului nu poți nici citi câmpurile, nici construi structura cuProdus { ... }(E0451). Adaugăpubcâmpurilor sau oferă o funcțienewpublică. - Scrii
modîn loc deusepentru a folosi un modul definit în altă parte.mod nume;declară (încarcă) modulul o singură dată, în părintele lui; în celelalte fișiere foloseștiuse crate::nume;.
Comenzi înrudite
use: Aduce în domeniu un nume dintr-un modul sau crate (std::collections::BTreeMap), ca să-l poți folosi fără calea completă.struct: Definește un tip nou care grupează mai multe valori cu nume (câmpuri), de exemplu un elev cu nume, clasă și medie.teste (#[test]): O funcție marcată cu #[test] este un test automat: cargo test o rulează și raportează dacă a trecut sau a dat panică.cargo new: Creează un proiect Rust nou: directorul, Cargo.toml, src/main.rs (sau src/lib.rs) și un depozit git.