Rust使用vs模块?

33

我对这些感到困惑,

  • use声明

    use声明创建一个或多个与其他路径同义的本地名称绑定。通常,use声明用于缩短引用模块项所需的路径。这些声明通常出现在模块和块中的顶部。

还有,

  • mod

    模块项是一个用大括号括起来的、命名的模块,以关键字mod为前缀。模块项将一个新的、命名的模块引入到构成一个crate的模块树中。模块可以任意嵌套。

基本上,当我开始布局我的模块时,我相信我知道我想要的布局方式,但是我对这两个东西应该如何层叠以及它们的作用感到困惑。我认为只有其中一个会包含代码,对吗?


15
简而言之,mod 表示“这是一个新模块(来自文件或花括号中),请将其存储以供将来使用”,use 表示“已经创建了一个模块,请从此路径中提取它并允许我在此处使用它”。 - Cerberus
4个回答

32
考虑你有一个模块my_mod,其中有一个公共函数my_func。在你的crate(或crate之外)中,如果你没有使用mod my_mod语句来包含你的模块,你就不能使用这个函数。
当你包含了你的模块之后,你可以像这样使用你的函数:
mod my_mod;

...
my_mod::my_func(...)
...

如果你没有在你的 crate 中包含你的模块,就不能使用 my_mod::my_func 语句。
有时候最好导入经常使用的定义:
mod my_mod;
use my_mod::my_func;

现在,如果你想使用你的函数,你只需要写下以下代码:
my_func(...);

你还可以使用pub use语句重新导出子模块(甚至其他的crate!)的定义。
如果你通过将它们列为依赖项在Cargo.toml中导入其他crate,你可以使用use语句从这些crate中导入定义。

谢谢@Dmitry,所以我的理解是,关键字"use"就像其他语言(如C#或C++)中的命名空间使用一样? - Jorge Fernandez Herrero
8
如果已经有了use,为什么还需要mod呢? - Alper
3
@Alper,如果模块没有被mod,则无法在另一个.rs文件中使用该模块。 - kafinsalim

16

编程语言文档试图解释,但错过了一些由mod意味着的重要概念,因此我不得不进行测试来弄清楚这一点。为了节省其他人的时间,我提供以下结论...

模块系统层次结构形成了一个类似于文件系统目录的源代码树,其中mod选择相对于其主机模块的直接子模块。重要的是,这些由mod引用的模块文件必须保存在一个子目录中,该子目录(1)位于与主机模块文件相同的目录中,并且(2)该子目录必须与主机模块文件具有相同的名称。这意味着模块不能导入兄弟、父母、孙子或表亲模块。*这种分层包含模式的明显例外,也许是许多混淆的根源是根模块(main.rs, lib.rs)。这些特定的模块文件确实出现在src/中,以及它们的子模块;然而,它们是特殊的。具体来说,这些创建根模块文件(main.rs, lib.rs, bin/other_root.rs)实际上被视为src/目录本身的父模块。(因此,在编译时,它们被视为命名为/src.rs,并带有关联的子目录/src/,或者(更好的是)作为根模块src/mod.rs,在src/目录本身中)。
创建根模块(以及Cargo.toml)通过选择src/目录中的模块来构建源代码树。然后,这些模块可以包括其关联模块子目录中的一部分,然后是这些模块的关联模块子目录中的模块,依此类推。所包含的模块文件树成为创建可用的源代码。重要的是,创建根模块(lib.rs, main.rs, bin/other_crate_root.rs)实际上可以从`/src'目录中选择不同的初始模块,从而演变出不同的模块树。
最后,一旦模块确实存在于创建的源代码树中,它就可以通过其路径引用(取决于可见性约束)。特别地,现在可以使用use语句来缩写到模块及其外部可见内容的路径。

你确定关于“只能导入直接子模块”的部分吗?使用crate::super::似乎是可能的(我称之为“绝对”和“相对”导入)。 - Gustavo Bezerra
"use" 与 "mod" 是不同的。 "use" 提供了源树内容的缩写引用。 "mod" 建立了源树。 - George

15

mod关键字就像import语句一样。你可以从外部文件中引入内容。

 // another_file is the name of the file, another_file.rs
 // file name is default module
 mod another_file

现在你带来了内容。`use` 用于创建顶层路径,这样你就可以在多个部分中使用函数或结构体。假设你需要访问模块中深层的结构体:
// mod could be in the same file: my_game::education::learning_rust::Person;
// in main.rs you dont need to use `use crate::another_file`. you would use `use crate` if you were in other module
use another_file::my_game::education::learning_rust::Person;

然后在main内部。
fn main(){
    let person=Person::new()
    person.display_info();
    }

如果我没有使用use关键字,每次需要Person结构体时,我会这样写:
let person=another_file::my_game::education::learning_rust::Person::new()

此外,如果您想要访问标准库的功能,可以使用use关键字。例如:
use std::net;
use std::io::prelude::*;

1
在你的例子中,mod语句和实际模块的mod声明之间有什么关系呢?所以如果我有一个名为a.rs的文件,在a.rs内部我这样定义一个模块:pub mod a。我想在主函数中使用a.rs中的函数,那么我是否仍然需要在主函数中再次使用mod a语句呢? - Raleigh L.

1
mod语句告诉编译器有一个它之前没有见过的文件。而use语句允许你将编译器已知的内容导入到本地作用域中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接