我正在使用 typestate 模式编写 Rust 代码来为其创建 API 和 CLI。
我有一个结构体
VendingMachine<S>
,其中S
是代表我当前状态的ZST(例如VendingMachine<Start>
,VendingMachine<Payment>
,VendingMachine<Checkout>
等)
我想让我的自动售货机循环运行并将每个状态与某些代码相匹配:
let mut machine = VendingMachine::new::<Start>(/*...*/);
loop {
match machine.state {
Start => {/* do something and then change the type of `machine` to VendingMachine<Payment> using some transitioning method */},
Payment => {/* do something else and then change the type of `machine` to VendingMachine<Checkout> using some other transitioning method */},
...
}
}
但是,编译器会拒绝此代码 - 如果我将匹配手臂中的“machine”重新绑定到如下转换的结果:
let machine = machine.to_payment();
其中
.to_payment()
有此签名:
fn to_payment(self) -> VendingMachine<Payment>
然后我收到“使用移动值:`machine.state`”错误,因为“在之前的循环迭代中,由于此 [to_ payment()] 方法调用,`machine` 发生了移动”
如何实现我需要的行为?
没有办法改变绑定的类型,这在 Rust 中是不可能的,因为编译后所有类型都会被忘记,如果类型完全不同,那么你就无法区分
VendingMachine<Start>
和 VendingMachine<Payment>
。为了能够将它们分开,您必须使用可以在运行时区分的东西,例如枚举。