单独文件中的结构如何相互引用?

时间:2017-04-06 17:28:56

标签: rust

使用相互引用的结构在单个文件中很常见,但是当我将结构分成两个文件时,我收到错误。

mod_1.rs

mod mod_2;
use mod_2::Haha;

pub struct Hehe {
    obj: Haha,
}

fn main() {
    Hehe(Haha);
}

mod_2.rs

mod mod_1;
use mod_1::Hehe;

pub struct Haha {
    obj: Hehe,
}

fn main() {
    Haha(Hehe);
}

这会产生错误。编译mod_1.rs

error: cannot declare a new module at this location
 --> mod_2.rs:1:5
  |
1 | mod mod_1;
  |     ^^^^^
  |
note: maybe move this module `mod_2` to its own directory via `mod_2/mod.rs`
 --> mod_2.rs:1:5
  |
1 | mod mod_1;
  |     ^^^^^
note: ... or maybe `use` the module `mod_1` instead of possibly redeclaring it
 --> mod_2.rs:1:5
  |
1 | mod mod_1;
  |     ^^^^^

编译mod_2.rs

error: cannot declare a new module at this location
 --> mod_1.rs:1:5
  |
1 | mod mod_2;
  |     ^^^^^
  |
note: maybe move this module `mod_1` to its own directory via `mod_1/mod.rs`
 --> mod_1.rs:1:5
  |
1 | mod mod_2;
  |     ^^^^^
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
 --> mod_1.rs:1:5
  |
1 | mod mod_2;
  |     ^^^^^

mod_1.rs 我使用 mod_2.rs mod_2.rs 中的内容,我使用< strong> mod_1.rs 的事情,所以我想找到摆脱循环参考模块问题的方法。

Trying to get Rust to load files是一个类似但不同的问题。

1 个答案:

答案 0 :(得分:6)

这是对Rust模块系统的常见误解。基本上,有两个步骤:

  1. 您必须构建模块树。这意味着此模块树中没有循环,并且节点之间存在明确的父子关系。这一步只是告诉Rust要加载哪些文件,并且与不同模块中某些符号的用法无关。

  2. 您现在可以通过其路径引用模块树中的每个符号(其中每个模块和最终符号名称由::分隔,例如std::io::read)。为了避免每次都写出完整路径,您可以使用use声明来通过简单名称引用特定符号。

  3. 您可以在in the Rust book chapter上阅读更多内容。

    同样,为了避免混淆:为了使用模块中的符号,您不要必须在模块中编写mod my_module;!对于项目的每个非根模块,整个项目中只有一个mod said_module;(根模块根本没有这样的行)。只有一次!

    关于您的示例:您首先通过mod_1.rs汇编了rustc mod_1.rs。这意味着mod_1是您案例中的根模块。如上所述,根模块根本不需要通过mod声明,但是所有其他模块需要正好声明一次。这意味着mod mod_2;中的mod_1.rs完全正确,但mod mod_1;中的mod_2.rs不正确。编译器甚至建议做正确的事情:

    note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
    

    您已经use了它,因此您只需删除行mod mod_1;并解决此错误。

    但是,我认为你仍在思考模块系统。如上所述,您首先需要设计一个或多或少固定的模块树,这意味着您有一个固定的根模块。无论您传递给rustc的是根模块,使用不同模块作为根模块都没有意义。在您的项目中应该有一个固定的根模块。如上所述,这可能是mod_1。但是,对于库,lib称为可执行文件,main通常更为惯用。

    再次:首先,在一张纸上绘制模块树。暂时考虑这个问题,然后你可以适当地创建文件和mod声明。

    最后一件事:即使在修复模块系统时,您的示例也无法正常工作,因为HahaHehe是无限大小的类型。结构的字段直接放入结构的内存布局中(不像Java那样装箱!)。因此,如果您手动添加一个间接层(如装箱字段),则不能在结构定义中使用之外的循环。有关此问题,请阅读this excellent explanation