Das Modulsystem von Rust ist tatsächlich unglaublich flexibel und ermöglicht es Ihnen, jede gewünschte Struktur verfügbar zu machen, während Sie verbergen, wie Ihr Code in Dateien strukturiert ist.
Ich denke, der Schlüssel hier ist die Verwendung pub use
, mit der Sie Bezeichner aus anderen Modulen erneut exportieren können. Es gibt einen Präzedenzfall dafür in Rusts std::io
Kiste, in der einige Typen aus Untermodulen zur Verwendung in erneut exportiert werdenstd::io
.
Bearbeiten (25.08.2019): Der folgende Teil der Antwort wurde vor einiger Zeit geschrieben. Es wird erklärt, wie Sie eine solche Modulstruktur einrichtenrustc
allein eingerichtet wird. Heutzutage würde man normalerweise Fracht für die meisten Anwendungsfälle verwenden. Während das Folgende noch gültig ist, #![crate_type = ...]
scheinen einige Teile davon (z. B. ) seltsam zu sein. Dies ist nicht die empfohlene Lösung.
Um Ihr Beispiel anzupassen, könnten wir mit dieser Verzeichnisstruktur beginnen:
src/
lib.rs
vector.rs
main.rs
Hier ist dein main.rs
:
extern crate math;
use math::vector;
fn main() {
println!("{:?}", vector::VectorA::new());
println!("{:?}", vector::VectorB::new());
}
Und dein src/lib.rs
:
#[crate_id = "math"];
#[crate_type = "lib"];
pub mod vector; // exports the module defined in vector.rs
Und schließlich src/vector.rs
:
// exports identifiers from private sub-modules in the current
// module namespace
pub use self::vector_a::VectorA;
pub use self::vector_b::VectorB;
mod vector_b; // private sub-module defined in vector_b.rs
mod vector_a { // private sub-module defined in place
#[derive(Debug)]
pub struct VectorA {
xs: Vec<i64>,
}
impl VectorA {
pub fn new() -> VectorA {
VectorA { xs: vec![] }
}
}
}
Und hier geschieht die Magie. Wir haben ein Untermodul definiert math::vector::vector_a
, in dem eine spezielle Art von Vektor implementiert ist. Wir möchten jedoch nicht, dass Kunden Ihrer Bibliothek sich darum kümmern, dass es ein vector_a
Untermodul gibt . Stattdessen möchten wir es im math::vector
Modul verfügbar machen . Dies geschieht mit pub use self::vector_a::VectorA
, wodurch die vector_a::VectorA
Kennung im aktuellen Modul erneut exportiert wird.
Sie haben jedoch gefragt, wie dies zu tun ist, damit Sie Ihre speziellen Vektorimplementierungen in verschiedenen Dateien ablegen können. Das macht die mod vector_b;
Leitung. Es weist den Rust-Compiler an, nach einer vector_b.rs
Datei für die Implementierung dieses Moduls zu suchen . Und natürlich ist hier unsere src/vector_b.rs
Akte:
#[derive(Debug)]
pub struct VectorB {
xs: Vec<i64>,
}
impl VectorB {
pub fn new() -> VectorB {
VectorB { xs: vec![] }
}
}
Aus Sicht des Kunden ist die Tatsache, dass VectorA
und VectorB
in zwei verschiedenen Modulen in zwei verschiedenen Dateien definiert sind, völlig undurchsichtig.
Wenn Sie sich im selben Verzeichnis wie befinden main.rs
, sollten Sie es ausführen können mit:
rustc src/lib.rs
rustc -L . main.rs
./main
Im Allgemeinen ist das Kapitel "Kisten und Module" im Rust-Buch ziemlich gut. Es gibt viele Beispiele.
Schließlich sucht der Rust-Compiler auch automatisch in Unterverzeichnissen nach Ihnen. Der obige Code funktioniert beispielsweise unverändert mit dieser Verzeichnisstruktur:
src/
lib.rs
vector/
mod.rs
vector_b.rs
main.rs
Die Befehle zum Kompilieren und Ausführen bleiben ebenfalls gleich.