Suche…
Syntax
- Modname ; // Suchen Sie das Modul in modname .rs oder modname /mod.rs im gleichen Verzeichnis
- mod modname { block }
Modulbaum
Dateien:
- example.rs (root of our modules tree, generally named lib.rs or main.rs when using Cargo)
- first.rs
- second/
- mod.rs
- sub.rs
Module:
- 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 {
...
}
Das second
Modul muss in der Datei example.rs
deklariert werden. Das first.rs
ist example
und nicht z. B. first
und kann daher nicht in der Datei first.rs
oder einer anderen Datei in derselben Verzeichnisebene deklariert werden
second/mod.rs
pub mod sub;
Das # [Pfad] -Attribut
Das #[path]
-Attribut von Rust kann verwendet werden, um den Pfad für die Suche nach einem bestimmten Modul anzugeben, wenn es sich nicht an der Standardposition befindet. Dies wird jedoch in der Regel nicht empfohlen , da die Modulhierarchie dadurch brüchig wird und der Build leicht durch Verschieben einer Datei in ein völlig anderes Verzeichnis unterbrochen werden kann.
#[path="../path/to/module.rs"]
mod module;
Namen im Code vs. Namen in "use"
Die Doppelpunkt-Syntax der Namen in der use
Anweisung sieht ähnlich aus wie die Namen, die an anderer Stelle im Code verwendet werden. Die Bedeutung dieser Pfade ist jedoch unterschiedlich.
Namen in der use
Anweisung werden standardmäßig als absolut interpretiert, beginnend am Kistenstamm. Namen an anderer Stelle im Code sind relativ zum aktuellen Modul.
Die Aussage:
use std::fs::File;
hat die gleiche Bedeutung in der Hauptdatei der Kiste sowie in Modulen. Ein Funktionsname wie std::fs::File::open()
verweist dagegen nur in der Hauptdatei der Kiste auf die Standardbibliothek von Rust, da die Namen im Code relativ zum aktuellen Modul interpretiert werden.
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");
}
}
Damit sich std::…
Namen überall gleich verhalten wie im Stamm der Kiste, könnten Sie Folgendes hinzufügen:
use std;
Umgekehrt können Sie machen use
Pfade relativ indem man sie mit prefixing self
oder super
- Schlüsselwörter:
use self::my_module::my_fn;
Zugriff auf das übergeordnete Modul
Manchmal kann es nützlich sein , um Importfunktionen und Strukturen relativ ohne zu haben , use
etwas mit seinem absoluten Pfad in Ihrem Projekt. Um dies zu erreichen, können Sie das Modul verwenden super
, etwa so:
fn x() -> u8 {
5
}
mod example {
use super::x;
fn foo() {
println!("{}", x());
}
}
Sie können super
mehrfach verwenden, um die "Großeltern" Ihres aktuellen Moduls zu erreichen. Sie sollten jedoch Bedenken hinsichtlich Lesbarkeitsproblemen haben, wenn Sie in einem Import zu oft super
.
Exporte und Sichtbarkeit
Verzeichnisaufbau:
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() {}
Basiscode-Organisation
Mal sehen, wie wir den Code organisieren können, wenn die Codebase größer wird.
01. Funktionen
fn main() { greet(); } fn greet() { println!("Hello, world!"); }
02. Module - In derselben Datei
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. Module - In einer anderen Datei im selben Verzeichnis
Wenn Sie Code in eine neue Datei verschieben, müssen Sie den Code nicht in eine mod
Deklaration mod
. Die Datei selbst fungiert als Modul.
// ↳ 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!"); }
Wenn ein Code in eine neue Datei verschoben wird und dieser Code aus einer
mod
Deklaration eingeschlossen wurde, ist dies ein Untermodul der Datei.
// ↳ 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. Module - In einer anderen Datei in einem anderen Verzeichnis
Wenn Sie Code in eine neue Datei in einem anderen Verzeichnis verschieben, fungiert das Verzeichnis selbst als Modul. Und mod.rs
im Modulstamm ist der Einstiegspunkt in das Verzeichnismodul. Alle anderen Dateien in diesem Verzeichnis fungieren als Untermodul dieses Verzeichnisses.
// ↳ main.rs mod greet; fn main() { greet::hello(); }
// ↳ greet/mod.rs pub fn hello() { println!("Hello, world!"); }
Wenn Sie mehrere Dateien im Modulstamm haben,
// ↳ 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. Module - Mit sich self
fn main() { greet::call_hello(); } mod greet { pub fn call_hello() { self::hello(); } fn hello() { println!("Hello, world!"); } }
06. Module - Mit super
- Wenn Sie innerhalb eines Moduls auf eine Root-Funktion zugreifen möchten,
fn main() { dash::call_hello(); } fn hello() { println!("Hello, world!"); } mod dash { pub fn call_hello() { super::hello(); } }
- Wenn Sie innerhalb eines verschachtelten Moduls auf eine Funktion im äußeren / übergeordneten Modul zugreifen möchten,
fn main() { outer::inner::call_hello(); } mod outer { pub fn hello() { println!("Hello, world!"); } mod inner { pub fn call_hello() { super::hello(); } } }
07. Module - Mit use
- Wenn Sie den vollständigen Pfad an einen neuen Namen binden möchten,
use greet::hello::greet as greet_hello; fn main() { greet_hello(); } mod greet { pub mod hello { pub fn greet() { println!("Hello, world!"); } } }
- Wenn Sie Inhalt der Kistenumfangsebene verwenden möchten
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(); } }