Rust模块
fn serve_order() {} mod back_of_house { fn fix_incorrect_order() { cook_order(); super::serve_order(); // 相当于父级目录下调用server_order函数 } fn cook_order() {} }
我们可以使用 super 进入back_of_house 父模块,也就是本例中的 crate 根。在这里,我们可以找到 serve_order 。成功!我们认为 back_of_house 模块和 server_order 函数之间可能具有某种关联关系,并且,如果我们要重新组织这个 crate 的模块树,需要一起移动它们。
mod back_of_house { pub struct Breakfast { pub toast: String, // 公有字段 seasonal_fruit:String, // 私有字段 } impl Breakfast { pub fn summer(toast: &str) -> Breakfast { Breakfast { toast:String::from(toast), seasonal_fruit:String::from("peaches"), } } } } pub fn eat_at_restaurant() { let mut meal = back_of_house::Breakfast::summer("Rye"); meal.toast = String::from("Wheat"); println!("I'd like {} toast please",meal.toast); // The next line won't compile if we uncomment it; we're not allowed // to see or modify the seasonal fruit that comes with the meal // meal.seasonal_fruit = String::from("blueberries"); // 编译不通过 }
因为 back_of_house::Breakfast 结构体的 toast 字段是公有的,所以我们可以在eat_at_restaurant 中使用点号来随意的读写 toast 字段。注意,我们不能在eat_at_restaurant 中使用 seasonal_fruit 字段,因为 seasonal_fruit 是私有的。尝试去除那一行修改 seasonal_fruit 字段值的代码的注释,看看你会得到什么错误!
还请注意一点,因为 back_of_house::Breakfast 具有私有字段,所以这个结构体需要提供一个公共的关联函数来构造示例 Breakfast (这里我们命名为 summer )。如果 Breakfast 没有这样的函数,我们将无法在 eat_at_restaurant 中创建 Breakfast 实例,因为我们不能在eat_at_restaurant 中设置私有字段 seasonal_fruit 的值。
mod back_of_house { pub enum Appetizer { Soup, Salad, } } pub fn eat_at_restaurant() { let order1 = back_of_house::Appetizer::Soup; let order2 = back_of_house::Appetizer::Salad; }
因为我们创建了名为 Appetizer 的公有枚举,所以我们可以在 eat_at_restaurant 中使用Soup 和 Salad 成员。如果枚举成员不是公有的,那么枚举会显得用处不大;给枚举的所有成员挨个添加 pub 是很令人恼火的,因此枚举成员默认就是公有的。结构体通常使用时,不必将它们的字段公有化,因此结构体遵循常规,内容全部是私有的,除非使用 pub 关键字。
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(); }
通过在 crate 根增加 use crate::front_of_house::hosting ,现在 hosting 在作用域中就是有效的名称了(绝对引用),我们也可以使用相对引用:
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } use front_of_house::hosting; // 相对引入模块 pub fn eat_at_restaurant() { hosting::add_to_waitlist(); hosting::add_to_waitlist(); hosting::add_to_waitlist(); }
引用起别名
Rust是不允许同时引入两个相同名字的模块:
use std::fmt; use std::io; fn function1() -> fmt::Result { // --snip-- # Ok(()) } fn function2() -> io::Result<()> { // --snip-- # Ok(()) } //如果我们是指定 use std::fmt::Result 和 use std::io::Result , //我们将在同一作用域拥有了两个 Result 类型, 当我们使用 Result 时,Rust 则不知道我们要用的是哪个。
use std::fmt::Result; use std::io::Result as IoResult; fn function1() -> Result { // --snip-- # Ok(()) } fn function2() -> IoResult<()> { // --snip-- # Ok(()) }
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } pub use crate::front_of_house::hosting; // pub use 使名称可引入任何代码的作用域中 重导出 pub fn eat_at_restaurant() { hosting::add_to_waitlist(); hosting::add_to_waitlist(); hosting::add_to_waitlist(); }
使用外部包
我们之前使用了rand依赖包,首先在 Cargo.toml 中加入了如下行:
[dependencies] rand = "0.5.5"
接着,为了将 rand 定义引入项目包的作用域,我们加入一行 use 起始的包名,它以rand 包名开头并列出了需要引入作用域的项。注意标准库( std )对于你的包来说也是外部 crate。因为标准库随 Rust 语言一同分发,无需修改 Cargo.toml 来引入 std ,不过需要通过 use 将标准库中定义的项引入项目包的作用域中来引用它们,比如我们使用的 HashMap :
use std::collections::HashMap;
如果是引入第三方包:
use rand::Rng;
当需要引入很多定义于相同包或相同模块的项时,为每一项单独列出一行会占用源码很大的空间。
use std::cmp::Ordering; use std::io; // ---snip--- // 修改为 use std::{cmp::Ordering, io};
我们可以在路径的任何层级使用嵌套路径,这在组合两个共享子路径的 use 语句时非常有用:
use std::io; use std::io::Write; // 修改为 use std::io::{self, Write}; // 可以在嵌套路径中使用 self
use std::collections::*;
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } pub use crate::front_of_house::hosting; // pub use 使名称可引入任何代码的作用域中重导出 pub fn eat_at_restaurant() { hosting::add_to_waitlist(); hosting::add_to_waitlist(); hosting::add_to_waitlist(); }
下面是我们分割后的代码,src下新建了一个front_of_house.rs文件,以及原有的lib.rs文件,首先看看lib.rs代码:
mod front_of_house; // mod关键字声明了模块,Rust 会在与模块同名的文件中查找模块的代码。 pub use crate::front_of_house::hosting; // pub use 使名称可引入任何代码的作用域中 重导出 pub fn eat_at_restaurant() { hosting::add_to_waitlist(); hosting::add_to_waitlist(); hosting::add_to_waitlist(); }
front_of_house.rs文件代码:
pub mod hosting { pub fn add_to_waitlist() {} }