Rust 学习笔记(五)|Rust 的代码组织

Rust中组织代码的方式即称为代码组织,它定义了对于外部调用者而言,哪些部分是私有的(private),哪些部分是公有的(public),作用域内哪些部分是有效的。在Rust中,使用模块系统将这些东西组合起来。

1 Package、Crate 和 Module

模块系统主要可以分为以下三个部分:

  • Package(包):一个Cargo特性,使开发者可以构建、测试和共享Crate;
  • Crate(单元包):一个模块(Module)树,可以产生库文件(Library Crate)或者可执行文件(Binary Crate);
  • Module(模块):让你控制代码的组织、作用域和私有路径,相当于基本的代码块单元;

1.1 Package 包

可以将一个工程理解为一个Package,它包含一个Cargo.toml文件,并根据这个文件构建多个Crate。一个Package只能有0-1个Library Crate,可以拥有多个Binary Crate,但必须至少有一个Crate。

1.2 Crate 单元包

Crate只有两种类型,即库(Library Crate)或者可执行文件(Binary Crate)。我们把一个源代码文件称为Crate Root,编译器从这里开始,组成Crate的根Module。按照一般惯例(Cargo默认,不在配置文件中体现),src/main.rs是Binary Crate的Crate Root,这个Crate的名字和Package的名字相同;src/lib.rs是Library Crate的Crate Root,这个Crate的名字和Package的名字也是相同的。Cargo会把Crate Root文件交给rustc编译器来构建Crate。使用Crate可以将相关功能组合到一个作用域内,便于在项目间进行共享,并且防止冲突。

当一个Package下有多个Binary Crate时,就需要将这些文件放在src/bin目录下,每个文件都是单独的Crate。

1.3 Module 模块

定义Module可以控制代码(或者条目,item)的作用域和私有性。在一个Crate内使用Module对代码进行分组,增强可读性并使其易于维护。Module是可以嵌套的。Module内可以包含struct、function、enum、trait、常量等定义。下面是一个定义Module的例子:在src/lib.rs文件中定义了一个Module的树形结构。

mod front_of_house {
    mod hosting {
        fn add_to_waitlists() {}
        fn seat_at_table() {}
    }
    
    mod serving {
        fn take_order() {}
        fn serve_order() {}
        fn take_payment() {}
    }
}

2 路径和私有边界

2.1 Path 路径

在Module代码块中,我们使用Path(路径)作为struct、function或者module的一种命名方式。这里的路径不是文件路径,而是表示代码的组织关系。路径分为绝对路径和相对路径。路径分隔符为::

  • 绝对路径:从Crate的名字或者crate关键字开始;
  • 相对路径:从自身开始,使用super或者self或者模块标识符表示。

默认情况下,Rust中的条目(struct、function等)都是私有的,使用pub关键字将某条目标记为公共的。父级模块无法访问子模块的私有条目,但是子模块可以访问所有祖先模块的所有条目。

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlists() {}
        fn seat_at_table() {}
    }
}

fn eat_at_restaurant() {
    front_of_house::hosting::add_to_waitlists();    // 相对路径
    
    crate::front_of_house::hosting::add_to_waitlists();     // 绝对路径
}

在上面的例子中,front_of_house模块和eat_at_restaurant函数都是根节点crate下面的条目,所以他们可以互相访问。同级别条目可以互相访问,不受私有边界(Private Boundary)的限制

使用super关键字可以访问上级目录的条目:

fn serve_order() {}

mod back_of_house {
    fn fix_incorrect_order() {
        super::serve_order();
        cook_order();
    }
    
    fn cook_order() {}
}

2.2 pub struct 和 pub enum

可以使用pub关键字将struct或者enum声明为公共的(默认私有),但是二者的不同点在于:struct成员默认私有,除非将其声明为公共;而enum成员默认共有(默认私有会使enum失去功能)。

下面是一个使用pub struct的例子:

mod back_of_house {
    pub struct Breakfast {
        pub toast: String,
        season_of_fruit: String,
    }
    
    impl Breakfast {
        pub fn summer(toast: &str) -> Breakfast {
            Breakfast {
                toast: String::from(toast),
                season_of_fruit: String::from("peaches"),
            }
        }
    }
}

pub fn eat_at_restaurant() {
    let mut meal = back_of_house::Breakfast::summer("Rye");
    
    meal.toast = String::from("Wheat");
    
    println!("I'd like {} toast please", meal.toast);
}

2.3 use 关键字

使用use关键字可以将制定条目导入到作用域内,引用时仍然需要遵守私有性规则。引用时可以使用绝对路径,也可以使用相对路径。

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;		// 绝对路径,相当于将hosting模块置于根crate下

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

如果要使用某个函数,一般引用到函数的父级模块,来提高代码的可读性;但是对于struct或者enum等其他条目,可以直接引用到它本身。如果要同时使用同一个父级模块的不同模块,可以使用as关键字进行简写:

use std::fmt::Result;
use std::io::Result as IoResult;

use关键字引入的条目仅对当前代码作用域有效,它默认也是私有的,如果外部代码也想访问本文件引入的条目,那么就需要使用pub use关键字对条目进行重导出。

可以使用嵌套路径对同一个父级模块的多个子条目进行引入:

use std::io::{self, Write, Result};		// 使用self引入本身

use std::collections::*;		// 使用*通配符引入所有子条目(通常在测试和预导入时使用)

3 将模块内容移动到其他文件

当定义模块时,如果模块后的名字是;而不是代码块,那么Rust就会从与模块同名的文件中加载内容,但是模块树的结构并不会发生变化。在使用这种方式导入其他文件中的内容时,需要注意模块的层级结构需要和文件系统的结构保持一致。

例如重构下面的代码:

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use front_of_house::hosting;		

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

use front_of_house::hosting;

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

转载声明:

除特殊声明外,本站所有文章均由 debussy 原创,均采用 CC BY-NC-SA 4.0 协议,转载请注明出处:Include Everything 的博客
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇