rust学习第6章

rust学习第6章

本文字数:1489  阅读时长:3分钟

访客数:加载中... | 阅读量:加载中...

Package Crate Module

  • Package(包): Cargo的特性 让你构建 测试 共享 crate

  • Crate(单元包): 一个模块树 它可产生一个library或可执行文件

  • Module(模块) use:让你控制代码的组织 作用域 私有路径

    Crate = 编译单元(binary 或 library)
    Package = 项目容器(1个 Cargo.toml + 若干 crates)
    一个 Package 最多 1 个 lib,任意数量 bin,至少 1 个 crate
    
text
my_project/                 ← Package 目录
├── Cargo.toml              ← Package 配置文件
├── src/
│   ├── lib.rs              ← Library crate root(可选,0-1个)
│   ├── main.rs             ← Binary crate root(默认)
│   └── bin/
│       ├── tool1.rs        ← 额外的 binary crate
│       └── tool2.rs        ← 额外的 binary crate

也就是说src/main.rs src/lib.rs都叫做crate roots

modle

rust
mod front_of_house{
    mod hosting{
        fn add_to_waitlist(){}
        fn seat_at_table(){}
    }
    mod serving{
        fn take_order(){}
        fn serve_order(){}
        fn take_patment(){}
    }
}

mod里可以包含多个mod

路径path

rust
mod front_of_house{
    mod hosting{
        fn add_to_waitlist(){}
        fn seat_at_table(){}
    }
}
pub fn eat_at_restaurant()
{
    crate::front_of_house::hosting::add_to_waitlist();//绝对路径
    front_of_house::hosting::add_to_waitlist();//相对路径
}

私有边界

  • Rust里所有的条目(函数 方法 struct enum 模块 常量)默认是私有的 那怎么变为公有的呢 pub关键字
  • 父级模块无法访问子模块中的私有条目
  • 对于加了pub关键字的enum其中的变体 也会变为公共的

super 类似于..返回上级

rust
fn serve_order(){}
mod back_of_house{
    fn fix_incorrect_order()
    {
        cook_order();
        super::serve_order();//跳出mod模块
        //对于mod内的就直接可以引用
        cook_order();
    }
    fn cook_order(){}
}

use

  • 可以使用use关键字将路径导入到作用域中但仍遵循私有性规则
  • 使用use可以用相对路径也可以用绝对路径
rust
mod front{
    pub mod hosting{
        pub fn add(){}
    }
}
use front::hosting;
pub fn eat(){
    hosting::add();
    hosting::add();
}
//当然了 也可以使用绝对路径也就是use creat::front::hosting
//虽然说可以直接写到某个函数 但是一般都只写到其父级
use front::hosting::add;
//这样也可以
pub fn eat(){
    add();
    add();
}
//但是一般不这样写 容易搞混

use的习惯用法

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

  • 对于struct enum 其他:制定完整路径(指定到本身)

  • 同名条目:指定到父级

    rust
    use std::fmt;
    use std::io;
    fn f1() -> fmt::Result{}
    fn f2() -> io::Result{}
    fn main(){}

    as 用法

    rust
    use std::fmt::Result as FmtResult;
    use std::io::Result as IoResult;
    fn f1() -> FmtResult{}
    fn f2() -> IoResult{}
    fn main(){}

    对比

    语言语法用途
    C++typedef 原类型 新名字类型别名
    C++11+using 新名字 = 原类型类型别名(更现代)
    Rustuse 原路径 as 新名字重命名导入
    Rusttype 新名字 = 原类型类型别名

    pub sue

    那么这时候就有人问了

    啊 主播主播 pub use用什么用 能用use引用的不都是pub了吗 为什么还要加一个pub

    好问题!并没人问

核心区别

关键字作用可见性
use把路径导入当前作用域仅当前模块可用
pub use把路径导入 + 重新导出当前模块 + 外部都可用

对比一下

rust
mod front {
    pub mod hosting {
        pub fn add() {}
    }
}

mod restaurant {
    // 1. 普通 use:只有 restaurant 内部能用
    use crate::front::hosting;
    
    pub fn eat() {
        hosting::add();  // ✅ 可以用
    }
}

// 外部代码
fn main() {
    // restaurant::hosting::add();  // ❌ 错误!hosting 不是 public 的
}
rust
mod restaurant {
    // 2. pub use:重新导出,外部也能用
    pub use crate::front::hosting;  // ⭐ 关键区别!
    
    pub fn eat() {
        hosting::add();
    }
}

// 外部代码
fn main() {
    restaurant::hosting::add();  // ✅ 现在可以了!
}

那么!又有人问了并没有

为什么不能像cpp的inxlude一样直接写在最外层 这样不就不需要pub了吗

这是个很好的问题!核心区别在于 Rust 的模块系统是有作用域的,而 C++ 的 #include 是文本替换

对于同一个包或模块下的多个条目 可以使用嵌套路径在同一行内进行引用–

rust
use std::cmp::Ordering;
use std::io;
//就可以换成下面这样
use std::{cmp::Ordering,io};

但是依旧有特殊情况

通配符*

和java一样

rust
use std::collections::*;

将模块内容放到其他文件

text
my_project/                 ← Package 目录
├── Cargo.toml              ← Package 配置文件
├── src/
    ├── lib.rs  
 	├── front.rs

lib.rs

rsut
mod front;
pub use crate::front::hosting;
pub fn eat()
{
	hosting::add();
}

front.rs

rsut
pub mod hosting{
	pub fn add(){}
}

你可以在lib.rs里引用mod(也就是front.rs)以;结尾

但是如果你想套娃就需要创建一个同名的文件夹

text
my_project/                 ← Package 目录
├── Cargo.toml              ← Package 配置文件
├── src/
    ├── lib.rs  
 	├── front.rs
  	├── front/
  		hosting.rs

像这样

至此第七章完结!

撒花!