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

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

问题描述

我想在其中具有多个结构的模块,每个在其自己的文件中.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.

我认为这里的关键是利用

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天全站免登陆