• Rust开发中的模块化管理
  • 发布于 2个月前
  • 171 热度
    0 评论
什么是Rust模块
模块是Rust中用于管理代码的结构。模块可以包含函数、常量、枚举、特质、结构体等元素。类似于C++中的命名空间和Python中的模块。我们可以通过使用mod 模块名 {}来创建模块。

创建模块并访问其函数
1. 完整的层级结构必须显式地设置为公共的,例如module_b和fun()。默认情况下,所有内容都是私有的,无法访问。
2. 函数可以通过绝对路径或相对路径来访问。
• 绝对路径:从crate根开始。
• 相对路径:从调用模块的当前作用域开始。//推荐使用
crate
└── module_a
    |── module_b
        ├── fun1
        └── fun2

mod module_a {
    pub mod module_b {              
        pub fn fun1() {              
            print!("fun");
        }
        fn fun2(){}
    }
}

fn main(){
    crate::module_a::module_b::fun1();   //绝对路径
    module_a::module_b::fun1();          //相对
    module_a::module_b::fun2();         //Error, 私有
}
这一种是最简单粗暴的做法,如果你要使用。记得要引入文件,要不代码无法读取正确的module。

super关键字
使用super关键字,我们可以构建从父模块开始的相对路径。这类似于在文件系统路径中使用..语法。
mod module_a {
    fn fun_a(){}
    pub mod module_b {
        fn fun_b(){}
        pub mod module_c {
            pub fn fun_c() {
                print!("fun_c");
            }
            //super::fun_a();     //无法编译。fun_a()不在父模块module_b中。
            super::fun_b();       //fun_b()在父模块module_b中,可以正常调用!
        }
    }
}

fn main(){
    crate::module_a::module_b::module_c::fun_c();   //绝对路径
    //module_a::module_b::fun();          //相对路径
}

////////类似于文件系统///////////
crate
    └── module_a
        ├── fun_a
        └── module_b      <-------
            ├── fun_b              |
            └── module_c          super可以访问父级(../)
                └── fun_c          |
                └── super ---------
模块内的结构体
1. 要访问结构体,必须将其声明为公共的,但结构体的所有字段默认仍然是私有的。
2. 要访问任何字段,该字段必须被设置为公共的。
3. 我们需要为module_a::st定义一个实现,以便访问其中的字段,因为存在私有成员。
4. 然后我们可以使用点标记法来访问成员。
mod module_a {
    pub struct st{           //1
        pub a:u32,          // 堆代码 duidaima.com
        b:u16,              //This remains pvt
    }

    impl test {                         //3
        pub fn fun(x: u32) -> st {
            st {
                a: x,
                b: 10,
            }
        }//fun
    }//test
}//module_a

pub fn fun1 {
    let mut var = crate::test::fun(30);         //4
    println!("{}", var.st.a);               //30
    println!("{}", var.st.b);               //10
}
模块内的枚举
与模块内的结构体不同,如果枚举是公共的,那么它的所有变体也是公共的。这与结构体不同,在结构体中,我们需要显式地将每个枚举变体设置为公共的。
mod module_a {
    pub enum Color {
        Red,          //如果枚举是公共的,所有枚举变体也是公共的
        Yellow,
    }
}

pub fn fun() {
    let var = module_a::Color::Red;
}
use 关键字
类似于C++中的类型别名/using关键字,use 用于将路径引入作用域。
mod module_a {
    pub mod module_b {
        pub fn fun() {}
    }
}

use crate::module_a::module_b;
pub fn fun1() {
    module_b::fun();      //现在 module_b 成为一个有效的名称(在 crate 作用域中定义)
}
use as
为路径定义更短的名称。
use std::fmt::Result as FmtResult;
use std::io::Result as IoResult;

fn function1() -> FmtResult {
    // --codeing--
}
fn function2() -> IoResult<()> {
    // --codeing--
}
pub use / 重新导出
使用 use 关键字将名称引入作用域后,该名称在新作用域中是私有的。要使其可用,我们可以结合 pub 和 use。这种技术称为重新导出,因为我们不仅将项目引入作用域,还使其可供其他人引入他们的作用域。
mod module_a {
    pub mod module_b {
        pub fn fun() {}
    }
}

pub use crate::module_a::module_b;

pub fn fun2() {
    module_b::fun();
}
真实案例
如果你的项目结构包含多个文件夹,你可以通过嵌套模块来组织代码。假设我们有以下项目结构:
my_project/
├── Cargo.toml
└── src/
    ├── main.rs
    ├── module_a/
    │   ├── mod.rs
    │   └── sub_module_a.rs
    └── module_b/
        ├── mod.rs
        └── sub_module_b.rs
在 main.rs 中,你可以声明模块并使用它们。
// src/main.rs
mod module_a;
mod module_b;

fn main() {
    module_a::function_a();
    module_b::function_b();
    module_a::sub_module_a::sub_function_a();
    module_b::sub_module_b::sub_function_b();
}
在 mod.rs 文件中声明子模块
在每个模块文件夹中,创建一个 mod.rs 文件,并在其中声明子模块。例如:
// src/module_a/mod.rs
pub mod sub_module_a;

pub fn function_a() {
    println!("Hello from module_a!");
}

// src/module_b/mod.rs
pub mod sub_module_b;

pub fn function_b() {
    println!("Hello from module_b!");
}
在子模块文件中定义子模块内容
在子模块文件中定义具体内容。例如:
// src/module_a/sub_module_a.rs
pub fn sub_function_a() {
    println!("Hello from sub_module_a!");
}

// src/module_b/sub_module_b.rs
pub fn sub_function_b() {
    println!("Hello from sub_module_b!");
}
使用 use 关键字简化路径
你可以使用 use 关键字来简化路径,使代码更简洁:
// src/main.rs
mod module_a;
mod module_b;

use module_a::sub_module_a::sub_function_a;
use module_b::sub_module_b::sub_function_b;

fn main() {
    module_a::function_a();
    module_b::function_b();
    sub_function_a();
    sub_function_b();
}
使用 pub use 重新导出
如果你希望在其他模块中使用某个模块的内容,可以使用 pub use 重新导出
// src/module_a/mod.rs
pub mod sub_module_a;

pub use sub_module_a::sub_function_a;

pub fn function_a() {
    println!("Hello from module_a!");
    sub_function_a();
}
调用的地方
// src/main.rs
mod module_a;
use module_a::sub_function_a;
fn main() {
    module_a::function_a();
    sub_function_a();
}
通过这种方式,你可以有效地组织和管理Rust项目中的代码,使其更具可读性和可维护性。

结论
模块提供了一种非常简单的方式,将代码分割成有意义的块,每个块可以相互交互或独立存在。
用户评论