모듈을 여러 파일로 분할
각각 자체 파일에 여러 구조체가있는 모듈을 갖고 싶습니다 . 사용하여 A Math
예로서 모듈 :
Math/
Vector.rs
Matrix.rs
Complex.rs
각 구조체가 동일한 모듈에 있기를 원하며 다음과 같이 기본 파일에서 사용할 것입니다.
use Math::Vector;
fn main() {
// ...
}
그러나 Rust의 모듈 시스템 (처음에는 약간 혼란 스럽습니다)은이를 수행하는 명백한 방법을 제공하지 않습니다. 전체 모듈을 하나의 파일로만 허용하는 것 같습니다. 소박하지 않습니까? 그렇지 않은 경우 어떻게해야합니까?
Rust의 모듈 시스템은 실제로 믿을 수 없을 정도로 유연하며 코드가 파일에서 어떻게 구조화되어 있는지 숨기면서 원하는 구조를 노출 할 수 있습니다.
여기서 핵심 pub use
은 다른 모듈에서 식별자를 다시 내보낼 수 있는를 사용 하는 것입니다. Rust의 std::io
상자에는 하위 모듈의 일부 유형 이 .NET에서 사용하기 위해 다시 내보내std::io
지는 선례가 있습니다 .
편집 (2019-08-25) : 답변의 다음 부분은 꽤 오래 전에 작성되었습니다. 이러한 모듈 구조를
rustc
단독 으로 설정하는 방법을 설명합니다 . 오늘날 대부분의 사용 사례에 일반적으로 Cargo를 사용합니다. 다음은 여전히 유효하지만 일부 (예#![crate_type = ...]
:)가 이상하게 보일 수 있습니다. 이것은 권장되는 솔루션이 아닙니다.
예제를 적용하기 위해 다음 디렉터리 구조로 시작할 수 있습니다.
src/
lib.rs
vector.rs
main.rs
여기 있습니다 main.rs
:
extern crate math;
use math::vector;
fn main() {
println!("{:?}", vector::VectorA::new());
println!("{:?}", vector::VectorB::new());
}
그리고 당신 src/lib.rs
:
#[crate_id = "math"];
#[crate_type = "lib"];
pub mod vector; // exports the module defined in vector.rs
그리고 마지막으로 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![] }
}
}
}
그리고 이것이 마법이 일어나는 곳입니다. 우리는 math::vector::vector_a
특별한 종류의 벡터를 구현 한 하위 모듈 을 정의했습니다 . 그러나 라이브러리의 클라이언트가 vector_a
하위 모듈 이 있다는 것을 신경 쓰지 않기를 바랍니다 . 대신 math::vector
모듈 에서 사용할 수 있도록하고 싶습니다 . 이것은 현재 모듈에서 식별자 pub use self::vector_a::VectorA
를 다시 내보내는으로 수행됩니다 vector_a::VectorA
.
그러나 특수한 벡터 구현을 다른 파일에 넣을 수 있도록이를 수행하는 방법을 물었습니다. 이것이 mod vector_b;
라인이하는 일입니다. Rust 컴파일러에게 vector_b.rs
해당 모듈의 구현을위한 파일 을 찾도록 지시합니다 . 여기에 src/vector_b.rs
파일이 있습니다.
#[derive(Debug)]
pub struct VectorB {
xs: Vec<i64>,
}
impl VectorB {
pub fn new() -> VectorB {
VectorB { xs: vec![] }
}
}
클라이언트의 관점에서 사실 VectorA
과 VectorB
두 개의 서로 다른 파일에 두 개의 서로 다른 모듈에 정의는 완전히 불투명하다.
와 같은 디렉토리에있는 경우 다음을 사용 main.rs
하여 실행할 수 있습니다.
rustc src/lib.rs
rustc -L . main.rs
./main
일반적으로 Rust 책 의 "Crates and Modules"장은 꽤 좋습니다. 많은 예가 있습니다.
마지막으로, Rust 컴파일러는 자동으로 하위 디렉토리를 찾습니다. 예를 들어 위의 코드는 다음 디렉토리 구조에서 변경되지 않고 작동합니다.
src/
lib.rs
vector/
mod.rs
vector_b.rs
main.rs
컴파일 및 실행 명령도 동일하게 유지됩니다.
Rust 모듈 규칙은 다음과 같습니다.
- 소스 파일 은 자체 모듈 일뿐입니다 (특수 파일 main.rs, lib.rs 및 mod.rs 제외).
- 디렉토리 는 모듈 경로 구성 요소입니다.
- The file mod.rs is just the directory's module.
The file matrix.rs1 in the directory math is just the module math::matrix
. It's easy. What you see on your filesystem you also find in your source code. This is an one-to-one correspondence of file paths and module paths2.
So you can import a struct Matrix
with use math::matrix::Matrix
, because the struct is inside the file matrix.rs in a directory math. Not happy? You'd prefer use math::Matrix;
very much instead, don't you? It's possible. Re-export the identifier math::matrix::Matrix
in math/mod.rs with:
pub use self::math::Matrix;
There's another step to get this working. Rust needs a module declaration to load the module. Add a mod math;
in main.rs. If you don't do that, you get an error message from the compiler when importing like this:
error: unresolved import `math::Matrix`. Maybe a missing `extern crate math`?
The hint is misleading here. There's no need for additional crates, except of course you really intend to write a separate library.
Add this at the top of main.rs:
mod math;
pub use math::Matrix;
The module declaration is also neccessary for the submodules vector
, matrix
and complex
, because math
needs to load them to re-export them. A re-export of an identifier only works if you have loaded the module of the identifier. This means, to re-export the identifier math::matrix::Matrix
you need to write mod matrix;
. You can do this in math/mod.rs. Therefore create the file with this content:
mod vector;
pub use self::vector::Vector;
mod matrix;
pub use self::matrix::Matrix;
mod complex;
pub use self::complex::Complex;
Aaaand you are done.
1Source file names usually start with a lowercase letter in Rust. That's why I use matrix.rs and not Matrix.rs.
2Java's different. You declare the path with package
, too. It's redundant. The path is already evident from the source file location in the filesystem. Why repeat this information in a declaration at the top of the file? Of course sometimes it's easier to have a quick look at the source code instead of finding out the filesystem location of the file. I can understand people who say it's less confusing.
Alright, fought my compiler for a while and finally got it to work(thanks to BurntSushi for pointing out pub use
.
main.rs:
use math::Vec2;
mod math;
fn main() {
let a = Vec2{x: 10.0, y: 10.0};
let b = Vec2{x: 20.0, y: 20.0};
}
math/mod.rs:
pub use self::vector::Vec2;
mod vector;
math/vector.rs
use std::num::sqrt;
pub struct Vec2 {
x: f64,
y: f64
}
impl Vec2 {
pub fn len(&self) -> f64 {
sqrt(self.x * self.x + self.y * self.y)
}
// other methods...
}
Other structs could be added in the same manner. NOTE: compiled with 0.9, not master.
Rusts purists will probably call me a heretic and hate this solution, but this is much simpler: just do each thing in its own file, then use the "include!" macro in mod.rs:
include!("math/Matrix.rs");
include!("math/Vector.rs");
include!("math/Complex.rs");
That way you get no added nested modules, and avoid complicated export and rewrite rules. Simple, effective, no fuss.
참고URL : https://stackoverflow.com/questions/22596920/split-a-module-across-several-files
'your programing' 카테고리의 다른 글
Java : 명령 줄 인수가 null인지 확인 (0) | 2020.10.07 |
---|---|
ARC를 사용한 @property 정의 : 강하거나 유지합니까? (0) | 2020.10.07 |
Gradle 버전 1.10이 필요합니다. (0) | 2020.10.07 |
요소를 주문하는 모범 사례는 무엇입니까? (0) | 2020.10.07 |
Node.js에서 실행되는 javascript에서 NPM 패키지를 설치할 수 있습니까? (0) | 2020.10.07 |