我想要一个包含多个 struct 的模块,each in its own file.Math模块为例:

Math/
  Vector.rs
  Matrix.rs
  Complex.rs

我希望每个 struct 都位于同一个模块中,我将从主文件中使用该模块,如下所示:

use Math::Vector;

fn main() {
  // ...
}

然而,Rust的模块系统(一开始有点混乱)并没有提供一个明显的方法来实现这一点.它似乎只允许您将整个模块放在一个文件中.这不是乡村风格吗?如果没有,我该怎么做?

推荐答案

Rust的模块系统实际上非常灵活,可以让你公开任何你想要的 struct ,同时隐藏代码在文件中的 struct .

我认为这里的关键是使用pub use,这将允许您从其他模块重新导出标识符.Rust的std::io crate 中有这样的先例,其中一些子模块的类型是re-exported for use in std::io.

Edit(2019-08-25):答案的以下部分是很久以前写的.它解释了如何设置这样一个模块 struct ,仅使用rustc个.今天,人们通常会在大多数用例中使用Cargo .虽然以下内容仍然有效,但其中的某些部分(例如#![crate_type = ...])可能看起来很奇怪.这不是推荐的解决方案.

为了适应您的示例,我们可以从以下目录 struct 开始:

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完成的,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![] }
    }
}

从客户的Angular 来看,VectorAVectorB在两个不同的模块中定义在两个不同的文件中,这一事实是完全不透明的.

如果你和main.rs在同一个目录下,你应该能够运行它:

rustc src/lib.rs
rustc -L . main.rs
./main

总的来说,铁 rust 书里的"Crates and Modules" chapter是相当不错的.有很多例子.

最后,Rust编译器还会自动查找子目录.例如,上面的代码将在这个目录 struct 下工作:

src/
  lib.rs
  vector/
      mod.rs
      vector_b.rs
main.rs

编译和运行的命令也保持不变.

Rust相关问答推荐

为什么我的梅森素数代码的指数越大,速度就越快?

borrow 和内部IntoIterator

如何最好地并行化修改同一Rust向量的多个切片的代码?

如何迭代属性以判断相等性?

为什么AsyncRead在Box上的实现有一个Unpin特征绑定?

如何设置activx websocket actorless的消息大小限制?

为什么HashMap::get和HashMap::entry使用不同类型的密钥?

为什么 tokio 在以奇怪的方式调用时只运行 n 个任务中的 n-1 个?

当推送到 HashMap 中的 Vector 时,类型 `()` 无法取消引用

闭包返回类型的生命周期规范

在Rust中实现Trie数据 struct 的更好方式

从 Rust 中的 if/else 中的引用创建 MappedRwLockWriteGuard

打印 `format_args!` 时borrow 时临时值丢失

为什么允许重新分配 String 而不是 *&String

为什么具有 Vec 变体的枚举没有内存开销?

没有分号的返回表达式的性能是否比使用返回更好?在Rust ?

是否有适当的方法在参考 1D 中转换 2D 数组

Rust 为什么 (u32, u32) 的枚举变体的大小小于 (u64)?

如何在不设置精度的情况下打印浮点数时保持尾随零?

为什么 Rust 标准库同时为 Thing 和 &Thing 实现特征?