如何在不拥有所有权的情况下替换结构字段的值

时间:2019-01-21 15:32:58

标签: rust ownership

(在"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中尝试不可能的设计?

1 个答案:

答案 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));
    }
}