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注释。

你可能感兴趣的:(rust)