乐趣区

关于rust:rust学习引用模块树中项目的路径Paths

为了向 Rust 展现在模块树中找到我的项目的地位,咱们应用的门路与浏览文件系统时应用的门路雷同。如果要调用函数,则须要晓得其门路。

门路能够采纳两种模式:
绝对路径从板条箱根开始通过应用一个 create 名称或一个文字 create。
相对路径从以后模块开始,并在以后模块中应用 self,super 或标识符。
绝对路径和相对路径后跟一个或多个标识符,并用双冒号分隔(::)

例如:

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();}

运行 cargo build 会报错:

D:\learn\cargo_learn>cargo build
   Compiling cargo_learn v0.1.0 (D:\learn\cargo_learn)
error[E0603]: module `hosting` is private
 --> src\lib.rs:9:28
  |
9 |     crate::front_of_house::hosting::add_to_waitlist();
  |                            ^^^^^^^ private module
  |
note: the module `hosting` is defined here
 --> src\lib.rs:2:5
  |
2 |     mod hosting {
  |     ^^^^^^^^^^^

error[E0603]: module `hosting` is private
  --> src\lib.rs:12:21
   |
12 |     front_of_house::hosting::add_to_waitlist();
   |                     ^^^^^^^ private module
   |
note: the module `hosting` is defined here
  --> src\lib.rs:2:5
   |
2  |     mod hosting {
   |     ^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0603`.
error: could not compile `cargo_learn`.

To learn more, run the command again with --verbose.

谬误音讯表明模块托管是公有的。换句话说,咱们领有托管模块和 add_to_waitlist 函数的正确门路,但 Rust 无法访问它们,因为它无法访问公有局部。

模块不仅仅对组织代码有用。它们还定义了 Rust 的隐衷边界:封装实现细节的行不容许内部代码晓得,调用或依赖。因而,如果要将我的项目设为函数或构造公有,则将其放在模块中。

Rust 中隐衷的工作形式是默认状况下所有我的项目(函数,办法,构造,枚举,模块和常量)都是公有的。父模块中的我的项目不能应用子模块中的公有我的项目,然而子模块中的我的项目能够应用其先人模块中的我的项目。起因是子模块包装并暗藏了其实现详细信息,然而子模块能够看到定义它们的上下文。要持续应用餐厅的隐喻,能够将隐衷规定视为餐厅的后盾办公室:餐厅客户的隐衷是私人的,但办公室经理能够查看并在其经营的餐厅中做任何事件。

Rust 抉择以这种形式使模块零碎起作用,以便默认暗藏外部实现细节。这样,您就晓得能够更改外部代码的哪些局部而不会毁坏内部代码。然而,您能够应用 pub 关键字将我的项目公开,从而将子模块代码的外部局部公开给内部先人模块。

因而咱们须要将应用到的 paths 裸露进去,通过应用关键字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();}

运行:cargo build

D:\learn\cargo_learn>cargo build
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s

D:\learn\cargo_learn>

通过 super 实现相对路径

在 rust 中 mod 中的函数通过应用 super:: 拜访与上一级同级别的 paths:

fn serve_order() {}

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

    fn cook_order() {}
}

fn main() {}

公开构造和枚举

咱们还能够应用 pub 将构造和枚举指定为公共,但还有一些其余细节。如果咱们在构造定义之前应用 pub,则将构造公开,但构造的字段仍将是公有的。咱们能够依据状况将每个字段公开或不公开。在下例中,咱们定义了一个公共的 back_of_house :: Breakfast 构造,其中蕴含一个公共的 toast 字段,但一个公有的 season_fruit 字段。这样能够在一家餐厅中模仿状况,客户能够在这家餐厅抉择餐点附带的面包类型,然而厨师会依据节令和库存来决定餐点中搭配哪种水果。可用的水果变动很快,因而客户无奈抉择水果,甚至看不到他们会失去哪种水果。

#![allow(unused_variables)]
fn main() {
    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() {
        // 通过 summer 订购黑麦面包早餐
        let mut meal = back_of_house::Breakfast::summer("Rye");
        // 扭转主见,想吃什么面包
        meal.toast = String::from("Wheat");
        println!("我喜爱 {} 吐司,谢谢", meal.toast);

        // 如果咱们勾销正文,则下一行将不会编译;咱们不容许查看或批改 seasonal_fruit
        // meal.seasonal_fruit = String::from("blueberries");
    }
}

与之不同的是,如果咱们将一个枚举公开,则其所有变体都将公开。咱们只须要 pub 在 enum 关键字之前,如下所示:

#![allow(unused_variables)]
fn main() {
    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 正文。

退出移动版