3.4.2 超越简单 Typestate
02-超越简单 Typestate — Comprehensive Rust
译文 · 基于 Comprehensive Rust
原文链接: https://google.github.io/comprehensive-rust/idiomatic/leveraging-the-type-system/typestate-pattern/typestate-advanced.html
超越简单 Typestate
如何管理日益复杂、有许多可能状态与转换的配置流程,同时仍防止不兼容的操作?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| # 3.4.2 超越简单 Typestate
// SPDX-License-Identifier: Apache-2.0
struct Serializer {/* [...] */}
struct SerializeStruct {/* [...] */}
struct SerializeStructProperty {/* [...] */}
struct SerializeList {/* [...] */}
impl Serializer {
// TODO,实现:
//
// fn serialize_struct(self, name: &str) -> SerializeStruct
// fn finish(self) -> String
}
impl SerializeStruct {
// TODO,实现:
//
// fn serialize_property(mut self, name: &str) -> SerializeStructProperty
// TODO,
// 我们应如何结束这个结构体?这取决于它出现在何处:
// - 在根层:返回 `Serializer`
// - 作为另一结构体内部的属性:返回 `SerializeStruct`
// - 作为列表内的值:返回 `SerializeList`
//
// fn finish(self) -> ???
}
impl SerializeStructProperty {
// TODO,实现:
//
// fn serialize_string(self, value: &str) -> SerializeStruct
// fn serialize_struct(self, name: &str) -> SerializeStruct
// fn serialize_list(self) -> SerializeList
// fn finish(self) -> SerializeStruct
}
impl SerializeList {
// TODO,实现:
//
// fn serialize_string(mut self, value: &str) -> Self
// fn serialize_struct(mut self, value: &str) -> SerializeStruct
// fn serialize_list(mut self) -> SerializeList
// TODO:
// 与 `SerializeStruct::finish` 类似,返回类型取决于嵌套位置。
//
// fn finish(mut self) -> ???
}
|
有效转换示意图:
+-----------+ +---------+------------+-----+
| | | | | |
V | V | V |
+ |
serializer --> structure --> property --> list +-+
| | ^ | ^
V | | | |
| +-----------+ |
String | |
+--------------------------+
在先前序列化器的基础上,我们现在想支持嵌套结构与列表。
但这同时引入了重复与结构复杂度。
更关键的是,我们现在碰到了类型系统限制:若不针对每种嵌套上下文(如根、结构体、列表)复制变体,就无法干净地表达 finish() 应返回什么。
从有效转换示意图可以观察到:
- 转换是递归的
- 返回类型取决于子结构或列表出现在_何处_
- 每个上下文都需要一条返回其父级的路径
仅用具体类型会变得难以管理。当前做法会导致类型爆炸与手工接线。
下一章我们将看到,泛型如何让我们用更少的样板代码建模递归流程,同时仍在编译期强制有效操作。