【Rust学习】7 Package和Crate定义module,

7.1 Package、Crate、定义Module

Rust 的代码组织

  • 代码组织主要包括:
    • 哪些细节可以暴露
    • 哪些细节是私有的作用域内
    • 哪些名称有效
  • 模块系统:
    • Package (包): Cargo 的特性,让你构建、测试、共享 crate
    • Crate (单元包):一个模块树,它可产生一个 library 或可执行文件
    • Module (模块)、use: 让你控制代码的组织、作用域、私有路径
    • Path (路径):为struct、function 或 module 等项命名的方式

Pacakge 和 Crate

  • Crate 的类型:
    • binary
    • library
  • Crate Root:
    • 是源代码文件
    • Rust 编译器从这里开始,组成你的 Crate 的根 Module
  • 一个Package
  • 包含1个 Cargo.toml,它描述了如何构建这些 Crates
  • 只能包含 0-1个 library crate
  • 可以包含任意数量的 binary crate
  • 但必须至少包含一个 crate (library 或 binary)

Cargo 的惯例

  • src/main.rs:

    • binary crate 的 crate root
    • crate 名与 package 名相同
  • src/lib.rs:

    • package 包含一个 library
    • crate library crate 的 crate root
    • crate 名与 package 名相同
  • 一个 Package 可以同时包含 src/main.rs 和 src/lib.rs

    • 一个 binary crate,一个library crate
    • 名称与 package 名相同
  • 一个 Package 可以有多个 binary crate

  • 文件放在 src/bin每个文件是单独的 binary crate

Crate 的作用

  • 将相关功能组合到一个作用域内,便于在项目间进行共享- 防止冲突
  • 例如 rand crate,访问它的功能需要通过它的名字: rand

定义 module 来控制作用域和私有性

  • Module:
    • 在一个 crate 内,将代码进行分组
    • 增加可读性,易于复用
    • 控制项目 (item)的私有性。public、private
  • 建module
    • mod关键字
    • 可嵌套
    • 可包含其它项 (struct、enum、常量、trait、函数等)的定义
mod front_of_house{
    mod hosting{
        fn add_to_waitlist(){}
        fn seat_to_table(){}
    }
}
mod serving{
    fn take_order(){}
    fn serve_order(){}
    fn take_payment(){}
}
  • src/main.rs 和 src/lib.rs 叫做 crate roots:
  • 这两个文件(任意一个)的内容形成了名为crate 的模块,位于整个模块树的根部

7.2&7.3 Path

路径 (Path)

  • 为了在 Rust 的模块中找到某个条目,需要使用路径
  • 路径的两种形式:
    • 绝对路径:从 crate root 开始,使用 crate 名或字面值 crate
    • 相对路径:从当前模块开始,使用 self,super 或当前模块的标识符
  • 路径至少由一个标识符组成,标识符之间使用 ::
  • 在同一个文件,就是在同一个crate
    • 用绝对路径和相对路径哪个好?
    • 还是使用绝对路径吧,这样后续移动代码方便
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();
}

报错
在这里插入图片描述

无法访问私有的

私有边界 (privacy boundary)

  • 模块不仅可以组织代码,还可以定义私有边界。
  • 如果想把 函数 或 struct 等设为私有,可以将它放到某个模块中。
  • Rust 中所有的条目 (函数,方法,struct,enum,模块,常量**)默认是私有的**
  • 父级模块无法访问子模块中的私有条目
  • 子模块里可以使用所有祖先模块中的条目

pub 关键字

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

super 关键字

super:用来访问父级模块路径中的内容,类似文件系统中的 …

fn serve_order(){}

mod back_of_house{
    fn fix_incorrect_order(){
        cook_order();
        super::serve_order();//相对
        crate::serve_order();//绝对
    }   
    fn cook_order(){}
}
fn main(){
    
}

pub struct

  • pub 放在 struct 前:
    • struct 是公共的
    • struct的字段默认是私有的
      struct 的字段需要单独设置 pub 来变成共有。
fn serve_order(){}

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"), 
            }
        }
    }
}
fn main(){
    let mut meal=back_of_house::Breakfast::summer("Rye");
    meal.toast=String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);
    meal.seasonal_fruit=String::from("apple");//报错,因为seasonal_fruit不是公有的
}

pub enum

  • pub 放在 enum 前:
    • enum 是公共的
    • enum 的变体也都是公共的
mod back_of_house{
    pub enum Appetizer {
        Soup,
        Salad
    } 
}

7.4&7.5 use关键字

  • 可以使用 use 关键字将路径导入到作用域内
    • 仍遵循私有性规则
mod front_of_house{
    pub mod hosting{
        pub fn add_to_waitlist(){}
        fn some_function(){}
    }
}
use crate::front_of_house::hosting;
fn main(){
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    // hosting::some_function();//报错,没有暴露这个方法

}
  • 使用use来指定相对路径

use 的习惯用法

  • 函数:将函数的父级模块引入作用域(指定到父级)

  • struct,enum,其它: 指定完整路径(指定到本身)

mod front_of_house{
    pub mod hosting{
        pub fn add_to_waitlist(){}
        fn some_function(){}
    }
}
use crate::front_of_house::hosting;
fn main(){
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    // hosting::some_function();//报错,没有暴露这个方法

}

为什么不直接引入add to waitlist?
如果这样做,就不知道这是本地定义的还是引入的,混淆所以引入上一级就可以

use std::collections::HashMap;
fn main(){
   let mut map=HashMap::new();
   map.insert(1, 2);
}

use的习惯用法

  • 函数:将函数的父级模块引入作用域(指定到父级)
  • struct,enum,其它: 指定完整路径(指定到本身)
  • 同名条目:指定到父级
use std::fmt;
use std::io;
fn f1()->fmt::Result{}
fn f2()->io::Result{}

as 关键字

as 关键字可以为引入的路径指定本地的别名

use std::collections::HashMap as map;
fn main(){
   let mut map=map::new();
   map.insert(1, 2);
}

使用 pub use 重新导出名称

  • 使用 use 将路径(名称)导入到作用域内后,该名称在此作用域内是私有的。
  • pub use: 重导出
    • 将条目引入作用域
    • 该条目可以被外部代码引入到它们的作用域
mod front_of_house{
    pub mod hosting{
        pub fn add_to_waitlist(){}
    }
}
pub use crate::front_of_house::hosting;
fn main(){
    hosting::add_to_waitlist();
    
}

使用外部包 (package

  • Cargo.toml添加依赖的包 (package)
    • https://crates.io/
  • use 将特定条目引入作用域

使用嵌套路径清理大量的 use 语句

  • 如果使用同一个包或模块下的多个条目(例子)

  • 可使用嵌套路径在同一行内将上述条目进行引入:

    • 路径相同的部分::{路径差异的部分}
      在这里插入图片描述
  • 如果两个 use 路径之一是另一个的子路径

    • 使用 self

通配符*

  • 使用*可以把路径中所有的公共条目都引入到作用域
  • 注意:谨慎使用
  • 应用场景:
    • 测试。将所有被测试代码引入到 tests 模块
    • 有时被用于预导入 (prelude) 模块
use std::collections::*;

将模块内容移动到其它文件

  • 模块定义时,如果模块名后边是“.”,而不是代码块
    • Rust 会从与模块同名的文件中加载内容
    • 模块树的结构不会变化

文件

mod front_of_house{
    pub mod hosting{
        pub fn add_to_waitlist(){}
    }
}
pub use crate::front_of_house::hosting;
fn main(){
    hosting::add_to_waitlist();
    
}

拆分
在这里插入图片描述

  • lib.rs
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant(){
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    
}
  • front_of_house.rs
pub mod hosting{
    pub fn add_to_waitlist(){}
}
  • front_of_house/hosting.rs
pub mod hosting;

将模块内容移动到其它文件

  • 模块定义时,如果模块名后边是“.”
    ,而不是代码块
    • Rust 会从与模块同名的文件中加载内容
    • 模块树的结构不会变化
  • 随着模块逐渐变大,该技术让你可以把模块的内容移动到其它文件中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值