将模块拆分为多个文件 [英] Split a module across several files

查看:25
本文介绍了将模块拆分为多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个包含多个结构的模块,每个都在自己的文件中.Math 模块为例:

I want to have a module with multiple structs in it, each in its own file. Using a Math module as an example:

Math/
  Vector.rs
  Matrix.rs
  Complex.rs

我希望每个结构都在同一个模块中,我将从我的主文件中使用它,如下所示:

I want each struct to be in the same module, which I would use from my main file, like so:

use Math::Vector;

fn main() {
  // ...
}

然而,Rust 的模块系统(一开始有点令人困惑)并没有提供一个明显的方法来做到这一点.它似乎只允许您将整个模块放在一个文件中.这不土气吗?如果没有,我该怎么做?

However Rust's module system (which is a bit confusing to begin with) does not provide an obvious way to do this. It seems to only allow you to have your entire module in one file. Is this un-rustic? If not, how do I do this?

推荐答案

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

Rust's module system is actually incredibly flexible and will let you expose whatever kind of structure you want while hiding how your code is structured in files.

我认为这里的关键是利用 pub use,这将允许您从其他模块重新导出标识符.这在 Rust 的 std::io 箱中有先例,其中子模块的某些类型是 重新导出用于 std::io.

I think the key here is to make use of pub use, which will allow you to re-export identifiers from other modules. There is precedent for this in Rust's std::io crate where some types from sub-modules are re-exported for use in std::io.

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

Edit (2019-08-25): the following part of the answer was written quite some time ago. It explains how to setup such a module structure with rustc alone. Today, one would usually use Cargo for most use cases. While the following is still valid, some parts of it (e.g. #![crate_type = ...]) might seem strange. This is not the recommended solution.

为了适应你的例子,我们可以从这个目录结构开始:

To adapt your example, we could start with this directory structure:

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 标识符.

And this is where the magic happens. We've defined a sub-module math::vector::vector_a which has some implementation of a special kind of vector. But we don't want clients of your library to care that there is a vector_a sub-module. Instead, we'd like to make it available in the math::vector module. This is done with pub use self::vector_a::VectorA, which re-exports the vector_a::VectorA identifier in the current module.

但是您询问了如何执行此操作,以便可以将您的特殊向量实现放在不同的文件中.这就是 mod vector_b; 行所做的.它指示 Rust 编译器查找 vector_b.rs 文件以实现该模块.果然,这是我们的 src/vector_b.rs 文件:

But you asked how to do this so that you could put your special vector implementations in different files. This is what the mod vector_b; line does. It instructs the Rust compiler to look for a vector_b.rs file for the implementation of that module. And sure enough, here's our src/vector_b.rs file:

#[derive(Debug)]
pub struct VectorB {
    xs: Vec<i64>,
}

impl VectorB {
    pub fn new() -> VectorB {
        VectorB { xs: vec![] }
    }
}

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

From the client's perspective, the fact that VectorA and VectorB are defined in two different modules in two different files is completely opaque.

如果您与 main.rs 位于同一目录中,您应该可以使用以下命令运行它:

If you're in the same directory as main.rs, you should be able to run it with:

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

一般来说,板条箱和模块"Rust 书中的章节 相当不错.有很多例子.

In general, the "Crates and Modules" chapter in the Rust book is pretty good. There are lots of examples.

最后,Rust 编译器还会自动为您查找子目录.例如,上面的代码将在使用此目录结构时保持不变:

Finally, the Rust compiler also looks in sub-directories for you automatically. For example, the above code will work unchanged with this directory structure:

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

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

The commands to compile and run remain the same as well.

这篇关于将模块拆分为多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆