Typestate模式是一种API设计模式,它将对象的运行时状态信息编码在其编译时的类型中。
当我们对一个对象的操作(如方法或函数),只有在该对象处于某些状态时才能使用:|
- “只有检查过它是有效的 UTF-8 后,才能翻译缓冲区。”
- “在文件句柄关闭后,您不得对文件句柄执行任何 I/O 操作。”
- “这些消息只能在身份验证成功后发送给客户端,而不是在我们结束会话之后。”
- “一旦你完成了动作 A,你必须先执行 B 或 C(但不能同时执行),然后才能执行 D。”
使用 typestate 模式,我们可以防止违反这些规则的代码编译,帮助程序员更早地发现错误并消除运行时检查的开销。
其他好处:
- 它与IDE很好地互动,可以避免建议在某一状态下的非法操作。
- 它可以消除运行时检查,使代码更快/更小。
这种模式在Rust中非常容易,几乎是显而易见的,以至于你可能已经写了使用它的代码,也许没有意识到这一点。有趣的是,它在大多数其他编程语言中很难实现--它们大多不能满足上述第2和/或第3项。
代码:
// 这里,我们还没有接触到一个文件。 |
std::fs::File 标准库有两种状态:“打开open”和“关闭close”。如果您可以访问一个文件,它就是open:获得它的唯一方法是通过 open操作。
如果继续操作:
drop(file)。 |
注意这里使用了drop方法:
pub fn drop<T>(value: T); |
这个drop方法特殊:是通过值来获取参数,而不是通过引用(&T),也就是说,值参数会被移到drop函数中,而外部调用者则失去了对它的访问,因为传递的是值,不是引用或指针。
Rust 的“传递”值会导致先前的所有者无法访问该值,而在大多数其他语言中,情况并非如此,其他语言大多数是引用传递。