Szukaj…
Składnia
- mod nazwa modowa ; // Wyszukaj moduł w modname .rs lub modname /mod.rs w tym samym katalogu
- mod nazwa modowa { blok }
Drzewo modułów
Akta:
- example.rs (root of our modules tree, generally named lib.rs or main.rs when using Cargo)
- first.rs
- second/
- mod.rs
- sub.rs
Moduły:
- 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 {
...
}
second moduł musi zostać zadeklarowany w pliku example.rs , ponieważ jego rodzicem jest example a nie, na przykład, first dlatego nie można go zadeklarować w pliku first.rs lub innym pliku na tym samym poziomie katalogu
second/mod.rs
pub mod sub;
Atrybut # [ścieżka]
Za pomocą atrybutu #[path] Rdza można określić ścieżkę wyszukiwania określonego modułu, jeśli nie znajduje się on w standardowej lokalizacji. Jest to jednak zwykle odradzane , ponieważ powoduje, że hierarchia modułów jest krucha i ułatwia przerwanie kompilacji poprzez przeniesienie pliku do zupełnie innego katalogu.
#[path="../path/to/module.rs"]
mod module;
Nazwy w kodzie kontra nazwy w `use`
Składnia podwójnych dwukropków nazw w instrukcji use wygląda podobnie do nazw używanych gdzie indziej w kodzie, ale znaczenie tych ścieżek jest inne.
Nazwy w instrukcji use są domyślnie interpretowane jako bezwzględne, zaczynając od katalogu głównego skrzynki. Nazwy w innym miejscu kodu odnoszą się do bieżącego modułu.
Wyrok:
use std::fs::File;
ma to samo znaczenie w głównym pliku skrzyni, a także w modułach. Z drugiej strony, nazwa funkcji, taka jak std::fs::File::open() będzie odnosić się do standardowej biblioteki Rusta tylko w głównym pliku skrzyni, ponieważ nazwy w kodzie są interpretowane względem bieżącego modułu.
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");
}
}
Aby nazwy std::… zachowywały się wszędzie tak samo, jak w katalogu głównym skrzynki, którą można dodać:
use std;
I odwrotnie, możesz use ścieżek względnych, poprzedzając je self lub super słowami kluczowymi:
use self::my_module::my_fn;
Dostęp do modułu nadrzędnego
Czasami przydatne może być względne importowanie funkcji i struktur bez konieczności use w projekcie projektu ścieżki absolutnej. Aby to osiągnąć, możesz użyć modułu super , tak jak:
fn x() -> u8 {
5
}
mod example {
use super::x;
fn foo() {
println!("{}", x());
}
}
Możesz użyć super wiele razy, aby dotrzeć do „dziadka” bieżącego modułu, ale powinieneś uważać na wprowadzanie problemów z czytelnością, jeśli użyjesz super zbyt wiele razy w jednym imporcie.
Eksport i widoczność
Struktura katalogów:
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() {}
Podstawowa organizacja kodu
Zobaczmy, jak możemy uporządkować kod, gdy baza kodów będzie się powiększać.
01. Funkcje
fn main() {
greet();
}
fn greet() {
println!("Hello, world!");
}
02. Moduły - w tym samym pliku
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. Moduły - w innym pliku w tym samym katalogu
Po przeniesieniu kodu do nowego pliku nie ma potrzeby zawijania kodu w deklaracji mod . Sam plik działa jak moduł.
// ↳ 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!");
}
Po przeniesieniu kodu do nowego pliku, jeśli kod ten został zawinięty z deklaracji
mod, będzie to podmoduł pliku.
// ↳ 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. Moduły - w innym pliku w innym katalogu
Po przeniesieniu kodu do nowego pliku w innym katalogu sam katalog działa jak moduł. A mod.rs w katalogu głównym modułu jest punktem wejścia do modułu katalogu. Wszystkie inne pliki w tym katalogu działają jako podmoduł tego katalogu.
// ↳ main.rs
mod greet;
fn main() {
greet::hello();
}
// ↳ greet/mod.rs
pub fn hello() {
println!("Hello, world!");
}
Gdy masz wiele plików w katalogu głównym modułu,
// ↳ 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. Moduły - z self
fn main() {
greet::call_hello();
}
mod greet {
pub fn call_hello() {
self::hello();
}
fn hello() {
println!("Hello, world!");
}
}
06. Moduły - z super
- Jeśli chcesz uzyskać dostęp do funkcji roota z wnętrza modułu,
fn main() {
dash::call_hello();
}
fn hello() {
println!("Hello, world!");
}
mod dash {
pub fn call_hello() {
super::hello();
}
}
- Jeśli chcesz uzyskać dostęp do funkcji w module zewnętrznym / macierzystym z wnętrza modułu zagnieżdżonego,
fn main() {
outer::inner::call_hello();
}
mod outer {
pub fn hello() {
println!("Hello, world!");
}
mod inner {
pub fn call_hello() {
super::hello();
}
}
}
07. Moduły - w use
- Jeśli chcesz powiązać pełną ścieżkę z nową nazwą,
use greet::hello::greet as greet_hello;
fn main() {
greet_hello();
}
mod greet {
pub mod hello {
pub fn greet() {
println!("Hello, world!");
}
}
}
- Gdy chcesz użyć zawartości zakresu skrzynek
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();
}
}