This commit is contained in:
nap.liu
2023-12-11 18:40:53 +08:00
parent d1b95f1096
commit 5dc4708fe2
79 changed files with 2269 additions and 39 deletions

7
10.Modules/10.1 Visibility/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "visibility"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "visibility"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,127 @@
//!
//! # 模块化
//!
//! Rust 提供了非常强大的模块化系统,可以按照等级拆分代码到小的模块中。
//! 模块中还可以通过 `pub` 关键字控制代码是否对外可见。
//!
//! 模块中可以放置 函数(function)、结构体(struct)、特性(trait)、和实现(impl)、甚至其他的模块(module)
//!
/// 默认情况下模块内部的所有内容都是私有(private)的,
/// 需要通过 `pub` 关键字来让私有变成外部可访问的。
// 模块名为 my_mod 的模块
mod my_mod {
// 模块内部的私有函数,模块外部不可见,也不能使用。
fn private_function() {
println!("called `my_mod::private_function()`");
}
// 使用 `pub` 关键字让 `function` 函数外面可以调用。
pub fn function() {
println!("called `my_mod::function()`");
}
// 公开的函数内部可以使用当前模块内的任意方法,不管使用的函数是不是公开的。
pub fn indirect_access() {
print!("called `my_mod::indirect_access()`, that\n> ");
private_function();
}
// 模块可以嵌套使用。
pub mod nested {
pub fn function() {
println!("called `my_mod::nested::function()`");
}
#[allow(dead_code)]
fn private_function() {
println!("called `my_mod::nested::private_function()`");
}
// 可以通过 `pub(in path)` 的语法来指定某些方法,只允许指定的父模块访问,
// `path` 只能是父模块或者祖先模块。
pub(in crate::my_mod) fn public_function_in_my_mod() {
print!("called `my_mod::nested::public_function_in_my_mod()`, that\n> ");
public_function_in_nested();
}
// 如果使用 `pub(self)` 关键字定义的话,那就表示该函数只能在当前模块内部使用,
// 等同于 private
pub(self) fn public_function_in_nested() {
println!("called `my_mod::nested::public_function_in_nested()`");
}
// `pub(super)` 等同于当前的父模块,`super` 关键字就是父模块的别名
pub(super) fn public_function_in_super_mod() {
println!("called `my_mod::nested::public_function_in_super_mod()`");
}
}
pub fn call_public_function_in_my_mod() {
print!("called `my_mod::call_public_function_in_my_mod()`, that\n> ");
nested::public_function_in_my_mod();
print!("> ");
nested::public_function_in_super_mod();
}
// pub(crate) 表示这个函数只允许在当前的包内可用,`crate` 等于当前的包
pub(crate) fn public_function_in_crate() {
println!("called `my_mod::public_function_in_crate()`");
}
// 嵌套的模块依旧遵循私有规则
mod private_nested {
#[allow(dead_code)]
pub fn function() {
println!("called `my_mod::private_nested::function()`");
}
// 因为当前模块没有对外公开,所以即使私有模块内部的方法公开了访问作用域,依旧还是不可见的。
#[allow(dead_code)]
pub(crate) fn restricted_function() {
println!("called `my_mod::private_nested::restricted_function()`");
}
}
}
fn function() {
println!("called `function()`");
}
fn main() {
// 因为模块有独立的作用域,所以可以避免同名函数的冲突问题。
function(); // 全局作用域的函数
my_mod::function(); // 模块内部的函数
// 在模块外面可以通过模块的名称,使用 `::` 作用域访问关键字访问模块内部的方法,或者嵌套在模块内部的模块。
my_mod::indirect_access();
my_mod::nested::function();
my_mod::call_public_function_in_my_mod();
// 使用 `pub(crate)` 声明的方法只要在同一个包crate中就可以随意使用。
my_mod::public_function_in_crate();
// 在模块中通过 `pub(in path)` 声明的方法,只能在 `path` 限定的地方使用
// 报错!函数 `public_function_in_my_mod` 是私有的
// my_mod::nested::public_function_in_my_mod();
// TODO ^ 移除注释查看错误
// 模块的私有项在外部不管什么情况下都不能被直接访问
// 报错! `private_function` 是私有的
//my_mod::private_function();
// TODO ^ 移除注释查看错误
// 报错! `private_function` 是私有的
//my_mod::nested::private_function();
// TODO ^ 移除注释查看错误
// 报错! `private_nested` 是私有模块
//my_mod::private_nested::function();
// TODO ^ 移除注释查看错误
// 报错! `private_nested` 是私有模块
//my_mod::private_nested::restricted_function();
// TODO ^ 移除注释查看错误
}

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "struct_visibility"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "struct_visibility"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,55 @@
//!
//! 模块中结构体的可见性
//!
//! 结构体的字段拥有一个额外的可见性配置,
//! 默认情况下结构体内部的字段对外都是不可见的,
//! 需要在每个字段上手动指定 `pub` 来让外部可以访问指定的字段,
//!
//!
mod my {
// 这个结构体对外可见
pub struct OpenBox<T> {
// 这个字段也对外可见
pub contents: T,
}
// 这个结构体对外可见
pub struct ClosedBox<T> {
// 这个字段外面不可见
#[allow(dead_code)]
contents: T,
}
impl<T> ClosedBox<T> {
// 结构体上拥有一个 `new` 方法是对外可见的
pub fn new(contents: T) -> ClosedBox<T> {
ClosedBox { contents }
}
}
}
fn main() {
// 如果结构体可见并且所有的字段也都对外可见的话,则可以直接声明字面量就能的到结构体实例
let open_box = my::OpenBox {
contents: "public information",
};
// 结构体的字段可以直接访问
println!("The open box contains: {}", open_box.contents);
// 公开的结构体如果有私有的字段,则不能直接使用字面量形式构造实例,因为私有字段对外不可见。
// 错误!`ClosedBox` 拥有不可见的私有字段。
// let closed_box = my::ClosedBox {
// contents: "classified information",
// };
// TODO ^ 移除注释查看错误
// 拥有私有结构的结构体可以通过结构上的公开的关联函数来构造结构体的实例。
let _closed_box = my::ClosedBox::new("classified information");
// 结构体的私有字段外部是不能访问的。
// 错误! `contents` 字段是私有的
// println!("The closed box contains: {}", _closed_box.contents);
// TODO ^ 移除注释查看错误
}

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "the_use_declaration"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "the_use_declaration"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,69 @@
//!
//! 使用 `use` 声明
//!
//! `use` 关键字可以把一个完整的路径在当前的作用域中,
//! 重新绑定到一个新的名字,这样可以减少完整路径的使用。
//!
//! 常用的几种形式如下
//!
//! ```
//! {
//! // 把 `std::rc::Rc` 使用 `Rc` 这个名字绑定到当前的作用域下
//! use std::rc::Rc;
//! }
//!
//! {
//! // 把 `std::rc::Rc` 使用 `StdRc` 这个名字绑定到当前的作用域下
//! use std::rc::Rc as StdRc;
//! }
//!
//! {
//! // 把 `std::rc` 下的所有导出项全都绑定到当前作用域下
//! use std::rc::*;
//! }
//!
//! {
//! // `self` 关键字代表的是前一级的路径,
//! // 在这里 `self` 等于把 `std::rc` 使用 `rc` 这个关键字绑定到当前作用域,
//! // 同时把 `std::rc::Rc` 使用 `StdRc` 绑定到当前作用域,
//! // 和 `std::rc::Weak` 使用 `Weak` 绑定到当前作用域。
//! use std::rc::{self, Rc as StdRc, Weak};
//! }
//!
//! ```
//!
// 把 `deeply::nested::function` 绑定到 `other_function`。
use deeply::nested::function as other_function;
fn function() {
println!("called `function()`");
}
mod deeply {
pub mod nested {
pub fn function() {
println!("called `deeply::nested::function()`");
}
}
}
fn main() {
// 使用重新绑定的名字调用 `deeply::nested::function`
other_function();
println!("Entering block");
{
// `crate` 代表当前的包,这里相当于把 `crate::deeply::nested::function` 重新绑定到当前作用域,名字叫 `function`
// 因为 `shadowing(遮蔽)` 的规则,`use` 关键字重新绑定的 `function` 会覆盖掉当前的全局作用域下的 `function` 函数。
use crate::deeply::nested::function;
// 这里调用的函数实际上是 `deeply::nested::function`
// 因为 `use` 关键字的重新绑定在当前的嵌套作用域中遮蔽了全局作用域下的 `function`
function();
println!("Leaving block");
}
function();
}

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "super_and_self"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "super_and_self"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,55 @@
//!
//! `super` 和 `self` 关键字
//!
//! 这两个关键字可以让硬编码的模块路径写成相对的路径关系。
//!
fn function() {
println!("called `function()`");
}
mod cool {
pub fn function() {
println!("called `cool::function()`");
}
}
mod my {
fn function() {
println!("called `my::function()`");
}
mod cool {
pub fn function() {
println!("called `my::cool::function()`");
}
}
pub fn indirect_call() {
// 在当前作用域中尝试访问所有的 `function` 函数!
print!("called `my::indirect_call()`, that\n> ");
// `self` 关键字明确的指出,我们要访问的作用域是当前的模块。
// 所以 `self::function()` 指明了我们调用的函数是当前模块中定义的函数。
self::function();
// 如果没有指明作用域,那么作用域等同于 `self`。
function();
// 可以使用 `self` 关键字来明确的指出,我们访问的是当前模块下定义的 `my` 子模块。
// `self` 关键字是可以省略的,因为当不指明作用域的时候等同于 `self`。
self::cool::function();
// `super` 关键字明确的指明了我们需要访问的是父模块中的方法,也就是当前的 `my` 模块的上一级。
super::function();
// 还可以通过 `crate` 特殊的作用域来重新从当前的包的根作用域下重新指定一个完整的路径。
{
use crate::cool::function as root_function;
root_function();
}
}
}
fn main() {
my::indirect_call();
}

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "file_hierarchy"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "file_hierarchy"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,28 @@
//!
//! 通过文件结构组织模块
//!
//! Rust 的模块可以按照文件的结构来组织,
//! 目录会当做一个子模块的查找路径。
//!
// 这个定义会让 `Rust` 去尝试查找 `my.rs` 或者 `my/mod.rs` 这个文件,并把该文件当做一个模块。
// `my` 模块的嵌套模块可以创建一个 `my` 的目录,把子模块放进去就可以了。
mod my;
fn function() {
println!("called `function()`");
}
fn main() {
// 调用 `my` 模块中的方法。
my::function();
// 调用全局作用域下的方法。
function();
// 再次调用 `my` 模块中的方法。
my::indirect_access();
// 调用 `my` 模块中嵌套的子模块的方法。
my::nested::function();
}

View File

@@ -0,0 +1,21 @@
// 把 `inaccessible.rs` 或 `inaccessible/mod.rs` 当做一个子模块引用进来,但是该模块对外不可见。
mod inaccessible;
// 把 `nested.rs` 或 `nested/mod.rs` 当做一个子模块引用进来,并且对外公开该模块。
pub mod nested;
// 定义公开方法
pub fn function() {
println!("called `my::function()`");
}
// 私有方法
fn private_function() {
println!("called `my::private_function()`");
}
// 公开方法中引用私有方法。
pub fn indirect_access() {
print!("called `my::indirect_access()`, that\n> ");
private_function();
}

View File

@@ -0,0 +1,5 @@
// 定义公开方法
#[allow(dead_code)]
pub fn public_function() {
println!("called `my::inaccessible::public_function()`");
}

View File

@@ -0,0 +1,10 @@
// 公开发方法
pub fn function() {
println!("called `my::nested::function()`");
}
// 私有方法
#[allow(dead_code)] // 这个是为了禁用未使用的警告,因为该函数是私有的,但是又没有任何地方访问它。
fn private_function() {
println!("called `my::nested::private_function()`");
}