模块暴露

pub 规则

结构,枚举,特征或模块的pub怎么样? pub 对他们来说是这样的:

  • Struct:将结构公开,但项目不公开。要公开一个项目,您也必须为每个项目都写一个 pub
  • Enum 或者 Trait:一切都公开了。这是有道理的,因为特质是关于赋予某物相同的行为。枚举是关于项目之间的选择的,您需要查看它们才能选择它们。
  • Module:第一个模块将是 pub,因为如果不是 pub,那么任何人都无法触摸其中的任何内容。但是模块内部的模块需要将 pub 公开。

因此,让我们在 print_things 中放置一个名为 Billy 的结构。这个结构几乎是所有公开的,但不是完全公开的。该结构是公共的,因此会说发布结构 Billy。里面会有一个名字和 times_to_print。名称不会是公共的,因为我们只希望用户创建名为 "Billy".to_string() 的结构。但是用户可以选择打印次数,这样可以公开显示。看起来像这样:

mod print_things {
    use std::fmt::{Display, Debug};

    #[derive(Debug)]
    pub struct Billy { // Billy is public
        name: String, // but name is private.
        pub times_to_print: u32,
    }

    impl Billy {
        pub fn new(times_to_print: u32) -> Self { // That means the user needs to use new to create a Billy. The user can only input times_to_print
            Self {
                name: "Billy".to_string(), // We choose the name - the user can't
                times_to_print,
            }
        }

        pub fn print_billy(&self) { // This function prints a Billy
            for _ in 0..self.times_to_print {
                println!("{:?}", self.name);
            }
        }
    }

    pub fn prints_one_thing<T: Display>(input: T) {
        println!("{}", input)
    }


}

fn main() {
    use crate::print_things::*; // Now we use *. This imports everything from print_things

    let my_billy = Billy::new(3);
    my_billy.print_billy();

}

"Billy"
"Billy"
"Billy"

模块嵌套

在 mod 内部,您可以创建其他 mod。子模块(模块内部的模块)始终可以使用父模块内部的任何模块。您可以在下一个示例中看到这一点,在该示例中,我们在 mod 国家的 mod 省内有一个 mod 城市。您可以想到这样的结构:即使您在一个国家中,也可能不在一个省中。即使您在省份中,也可能不在城市中。但是,如果您在城市中,那么您将在其省份中,并且您是其国家/地区。

mod country { // The main mod doesn't need pub
    fn print_country(country: &str) { // Note: this function isn't public
        println!("We are in the country of {}", country);
    }
    pub mod province { // Make this mod public

        fn print_province(province: &str) { // Note: this function isn't public
            println!("in the province of {}", province);
        }

        pub mod city { // Make this mod public
            pub fn print_city(country: &str, province: &str, city: &str) {  // This function is public though
                crate::country::print_country(country);
                crate::country::province::print_province(province);
                println!("in the city of {}", city);
            }
            }
        }
    }

fn main() {
    crate::country::province::city::print_city("Canada", "New Brunswick", "Moncton");
}

有趣的是,print_city 可以访问 print_province 和 print_country。这是因为 mod city 在其他 mod 内。它不需要在 print_province 前面的 pub 来使用它。这是有道理的:城市不需要在省内和国家内做任何事情。您可能注意到了 crate::country::province::print_province(province); 很长,当我们在模块内部时,我们可以使用 super 从上方引入项目。实际上,“超级”一词本身的意思是“在…之上”,就像在“高级”中一样。在我们的示例中,我们只使用了一次函数,但是如果您再使用一次,则导入是个好主意。如果它使您的代码更易于阅读,即使您只使用一次该函数,也是一个好主意。现在的代码几乎相同,但更易于阅读:

mod country {
    fn print_country(country: &str) {
        println!("We are in the country of {}", country);
    }
    pub mod province {
        fn print_province(province: &str) {
            println!("in the province of {}", province);
        }

        pub mod city {
            use super::super::*; // use everything in "above above": that means mod country
            use super::*;        // use everything in "above": that means mod province

            pub fn print_city(country: &str, province: &str, city: &str) {
                print_country(country);
                print_province(province);
                println!("in the city of {}", city);
            }
        }
    }
}

fn main() {
    use crate::country::province::city::print_city; // bring in the function

    print_city("Canada", "New Brunswick", "Moncton");
    print_city("Korea", "Gyeonggi-do", "Gwangju"); // Now it's less work to use it again
}

Re-exporting

我们可以结合使用 pub use 来实现 Re-exportingRe-exporting 的字面意思就是重新导出。它的意思是这样的,把深层的 item 导出到上层目录中,使调用的时候,更方便。接口设计中会大量用到这个技术。对于深层引用 a::b::c::d 的例子。我们在 main.rs 中,要调用 d,得使用 use a::b::c::d; 来调用。而如果我们修改 a/mod.rs 文件为:a/mod.rs 文件内容:

pub mod b;
pub use b::c::d;

那么,我们在 main.rs 中,就可以使用 use a::d; 来调用了。从这个例子来看没觉得方便多少。但是如果开发的一个库中有大量的内容,而且是在不同层次的模块中。那么,通过统一导出到一个地方,就能大大方便接口使用者。

下一页