06.使用包、单元包以及模块

包(package):一个用于构建、测试并分享单元包的Cargo功能;
单元包(crate):一个用于生成库或可执行文件的树形模块结构;
模块(module)及use关键字:它们被用于控制文件结构、作用域及路径的私有性;
路径(path):一种用于命名条目的方法,这些条目包括结构体、函数和模块等;

一、包与单元包

单元包可以被用于生成二进制程序或库,同事它也是单元包的根模块。
包则是由一个或多个提供相关功能的单元包集合而成,它所附带的配置文件Cargo.toml描述了如何构建这些单元包的信息。

  1. 一个包中只能拥有最多一个库单元包;
  2. 包可以拥有任意多个二进制单元包;
  3. 包内必须存在至少一个单元包(库单元包或二进制单元包)

二、通过定义模块来控制作用域及私有性

模块允许我们将单元包内的代码按照可读性与易用性来进行分组。它允许我们控制条目的私有性。
mod关键字开头来定义一个模块,接着指明这个模块的名字,并在其后使用一对花括号来包括模块体。
src/main.rssrc/lib.rs被称作单元包的根节点,因为这两个文件的内容各自组成了一个名为crate的模块,并位于单元包模块结构的根部。这种模块结构也称为模块树。

注意,整个模块书都被防止在一个名为crate的隐式根模块下。

三、用于在模块树中指明条目的路径

路径有两种形式:

  • 使用单元包名或字面量crate从根节点开始的绝对路径;
  • 使用selfsupper或内部标识符从当前模块开始的相对路径;
    绝对路径与相对路径都由至少一个标识符组成,标识符之间使用双冒号(::)分隔。
mod front_of_house {
    mod hosting {
        fn add_to_waitlist() {}
    }
}

pub fn eat_at_restaurant() {
    // 绝对路径
    crate::front_of_house::hosting::add_to_waitlist();

    // 相对路径
    front_of_house::hosting::add_to_waitlist();
}

Rust中的所有条目(函数、方法、结构体、枚举、模块及常量)默认都是私有的。处于父级模块中的条目无法使用子模块中的私有条目,但子模块中的条目可以使用它所有父级模块中的条目,从而减少暴露内部代码细节。

1、使用pub关键字暴露路径

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

pub fn eat_at_restaurant() {
    // 绝对路径
    crate::front_of_house::hosting::add_to_waitlist();

    // 相对路径
    front_of_house::hosting::add_to_waitlist();
}

在绝对路径,我们从 crate,也就是 crate 根开始。然后 crate 根中定义了 front_of_house 模块。front_of_house 模块不是公有的,不过因为 eat_at_restaurant 函数与 front_of_house 定义于同一模块中(即,eat_at_restaurant 和 front_of_house 是兄弟),我们可以从 eat_at_restaurant 中引用 front_of_house。接下来是使用 pub 标记的 hosting 模块。我们可以访问 hosting 的父模块,所以可以访问 hosting。最后,add_to_waitlist 函数被标记为 pub ,我们可以访问其父模块,所以这个函数调用是有效的!
在相对路径,其逻辑与绝对路径相同,除了第一步:不同于从 crate 根开始,路径从 front_of_house 开始。front_of_house 模块与 eat_at_restaurant 定义于同一模块,所以从 eat_at_restaurant 中开始定义的该模块相对路径是有效的。接下来因为 hosting 和 add_to_waitlist 被标记为 pub,路径其余的部分也是有效的,因此函数调用也是有效的!

2、使用super起始的相对路径

使用supser开头来构建从父模块开始的相对路径。

fn serve_order() {}

mod back_of_house {
    fn fix_incorrect_order() {
        cook_order();
        super::serve_order();
    }

    fn cook_order() {}
}

3、创建公有的结构体和枚举

将枚举设置为公有,那么枚举成员默认也是公有的。结构体通常使用时,不必将它们的字段公有化,因此结构体遵循常规,内容全部是私有的,除非使用pub关键字。

四、用use关键字将路径导入作用域

借用use关键字将路径引入作用域。在作用域中使用use引入路径有些类似于在文件系统中创建符号链接。当使用use将路径引入作用域中也需要遵守私有性规则。

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

在作用域中使用use引入路径有些类似于在文件系统中创建符号链接。通过在单元包的根节点下添加use crate::front_of_house::hosting;,让hosting成为了该作用域下的一个有效名称。

1、使用as关键字来提供新的抿成

使用use将同名类型引入作用域时所产生的问题,可以使用as关键为类型指定一个新的本地名称,也称为别名。

use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    // --snip--
    Ok(())
}

fn function2() -> IoResult<()> {
    // --snip--
    Ok(())
}
posted @ 2022-11-24 21:10  Diligent_Maple  阅读(90)  评论(0编辑  收藏  举报