15、16、17 章完结

This commit is contained in:
nap.liu
2023-12-15 09:20:45 +08:00
parent 5dc4708fe2
commit aa96369aed
20 changed files with 1941 additions and 1 deletions

View File

@@ -30,6 +30,54 @@ struct PhantomStruct<A, B> {
// 注意:代码编译的时候只会为正常的泛型 `A` 申请空间,而幽灵类型 `B` 没有空间,
// 所以使用了幽灵类型 `B` 的字段或者位置都不能当做实际存在的类型使用。
// 幽灵小测试
fn testcase_unit_clarification() {
// use std::marker::PhantomData;
use std::ops::Add;
/// 创建两个枚举类型
#[derive(Debug, Clone, Copy)]
enum Inch {}
#[derive(Debug, Clone, Copy)]
enum Mm {}
/// `Length` 是一个拥有幽灵泛型 `Unit` 的一个元组结构,
/// 我们明确指定了元组拥有一个 `f64` 的实际类型,
/// f64 天然实现了 `Clone` 和 `Copy` 特性。
#[derive(Debug, Clone, Copy)]
struct Length<Unit>(f64, PhantomData<Unit>);
/// `Add` 特性会重定义 `Length<Unit>` 这个类型的 `+` 操作符。
impl<Unit> Add for Length<Unit> {
type Output = Length<Unit>;
// add() 返回一个新的 `Length` 结构保存着加法的结果。
fn add(self, rhs: Length<Unit>) -> Length<Unit> {
// 实现 `+` 号的操作。
Length(self.0 + rhs.0, PhantomData)
}
}
// 明确指明幽灵类型的实际类型是 `Inch`。
let one_foot: Length<Inch> = Length(12.0, PhantomData);
// 明确指明幽灵类型的实际类型是 `Mm`。
let one_meter: Length<Mm> = Length(1000.0, PhantomData);
// 因为我们重定义了 `Length` 类型的 `+` 号操作符,所以这里可以直接使用 `+` 号进行计算,
// 而 `Length` 类型实现了 `Copy` 特性,所以 `add()` 会优先使用 `Copy` 方法来复制一个副本进行所有权的转移,
// 所以这里同一个变量使用两次才不会报错。
let two_feet = one_foot + one_foot;
let two_meters = one_meter + one_meter;
// 加法操作正常。
println!("one foot + one_foot = {:?} in", two_feet.0);
println!("one meter + one_meter = {:?} mm", two_meters.0);
// 没有意义的对比。
// 编译错误: 类型不匹配
// let one_feter = one_foot + one_meter;
}
fn main() {
// 这里的 `f32` 和 `f64` 类型是给幽灵类型使用的。
// PhantomTuple type specified as `<char, f32>`.
@@ -55,4 +103,7 @@ fn main() {
// 编译错误!类型匹配不能对比
// println!("_struct1 == _struct2 yields: {}", _struct1 == _struct2);
// 幽灵类型小测试
testcase_unit_clarification();
}