Sistem modul Rust sebenarnya sangat fleksibel dan akan membiarkan Anda mengekspos jenis struktur apa pun yang Anda inginkan sambil menyembunyikan bagaimana kode Anda disusun dalam file.
Saya pikir kuncinya di sini adalah memanfaatkan pub use
, yang akan memungkinkan Anda mengekspor ulang pengenal dari modul lain. Ada preseden untuk ini di std::io
peti Rust di mana beberapa jenis dari sub-modul diekspor kembali untuk digunakan distd::io
.
Sunting (2019-08-25): bagian jawaban berikut ditulis beberapa waktu yang lalu. Ini menjelaskan bagaimana mengatur struktur modul seperti itu dengan rustc
sendiri. Saat ini, orang biasanya akan menggunakan Cargo untuk sebagian besar kasus penggunaan. Meskipun berikut ini masih berlaku, beberapa bagiannya (mis. #![crate_type = ...]
) Mungkin tampak aneh. Ini bukan solusi yang disarankan.
Untuk mengadaptasi contoh Anda, kita bisa mulai dengan struktur direktori ini:
src/
lib.rs
vector.rs
main.rs
Ini milik Anda main.rs
:
extern crate math;
use math::vector;
fn main() {
println!("{:?}", vector::VectorA::new());
println!("{:?}", vector::VectorB::new());
}
Dan Anda src/lib.rs
:
#[crate_id = "math"];
#[crate_type = "lib"];
pub mod vector; // exports the module defined in vector.rs
Dan akhirnya, 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![] }
}
}
}
Dan di sinilah keajaiban terjadi. Kami telah mendefinisikan sub-modul math::vector::vector_a
yang memiliki beberapa implementasi dari jenis vektor khusus. Tapi kami tidak ingin klien perpustakaan Anda peduli bahwa ada vector_a
sub-modul. Sebagai gantinya, kami ingin membuatnya tersedia di math::vector
modul. Ini dilakukan dengan pub use self::vector_a::VectorA
, yang mengekspor ulang vector_a::VectorA
pengenal di modul saat ini.
Tetapi Anda bertanya bagaimana melakukan ini sehingga Anda dapat meletakkan implementasi vektor khusus Anda di file yang berbeda. Inilah yang mod vector_b;
garis itu lakukan. Ini menginstruksikan kompiler Rust untuk mencari vector_b.rs
file untuk implementasi modul itu. Dan tentu saja, inilah src/vector_b.rs
file kami :
#[derive(Debug)]
pub struct VectorB {
xs: Vec<i64>,
}
impl VectorB {
pub fn new() -> VectorB {
VectorB { xs: vec![] }
}
}
Dari perspektif klien, fakta bahwa VectorA
dan VectorB
didefinisikan dalam dua modul berbeda dalam dua file berbeda benar-benar tidak jelas.
Jika Anda berada di direktori yang sama dengan main.rs
, Anda harus dapat menjalankannya dengan:
rustc src/lib.rs
rustc -L . main.rs
./main
Secara umum, chapter "Crates and Modules" di buku Rust cukup bagus. Ada banyak contoh.
Akhirnya, kompilator Rust juga mencari di sub-direktori untuk Anda secara otomatis. Misalnya, kode di atas tidak akan berfungsi dengan struktur direktori ini:
src/
lib.rs
vector/
mod.rs
vector_b.rs
main.rs
Perintah untuk mengkompilasi dan menjalankan juga tetap sama.