(在"cannot move out of borrowed content" when replacing a struct field之后)
我有一个第三方API,其中一个结构具有使用该实例并返回一个新实例的方法;我想将此API包装在自己的包装器中,并抽象出该操作中使用该结构的细节。
此示例说明了我要实现的目标:
// Third-party API
struct Item {
x: u32,
}
impl Item {
pub fn increment(self, amount: u32) -> Self {
Item { x: self.x + amount }
}
}
// My API
struct Container {
item: Item,
}
impl Container {
pub fn increment_item(&mut self, amount: u32) {
// This line causes "cannot move out of borrowed content" but this is exactly what I want to do
self.item = self.item.increment(amount);
}
}
现在我明白了这个错误,我想知道如何在不拥有self
内部Container::increment_item
所有权的情况下实现此错误。
建议的解决方案:
Item::increment
改为&mut self
,而不是self
:我不能,Item::increment
来自板条箱。mem::replace
(来自here):不幸的是,构造一个Item
实例并不是那么容易,而且老实说,我还不完全了解mem::replace
解决方案有效。Container::increment_item
改为self
,而不是&mut self
:我不想在此过程中消耗Container
实例,我我正在尝试将包装材料设计得尽可能符合人体工程学,并完全抽象化{em> Item
在更改时必须使用的事实。有关如何执行操作的一些想法?还是我在Rust中尝试不可能的设计?
答案 0 :(得分:2)
最简单的方法是使用Option
:
take
取得该项目的所有权,Some(...)
。如果Option
为空时发生了紧急情况,这是绝对安全的。不会发生双重破坏,并且如果您愿意,容器甚至可以保持可用。
或在代码中
// Third-party API
struct Item {
x: u32,
}
impl Item {
pub fn increment(self, amount: u32) -> Self {
Item { x: self.x + amount }
}
}
// My API
struct Container {
item: Option<Item>,
}
impl Container {
pub fn increment_item(&mut self, amount: u32) {
let item = self.item.take().unwrap();
self.item = Some(self.item.increment(amount));
}
}