如何在 Rust 中将对象用作其自身方法的参数?

How can I use an object as a parameter of its own method in Rust?

我在 Rust 中为一个简单的结构编写了以下代码。这只是一个例子,并没有太多真正的逻辑:

struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&mut self, other: &Vec2) {
        self.x *= other.x;
        self.y *= other.y;
    }
}

我可以创建简单的向量并将一个向量与另一个向量相乘,但是当我尝试将一个向量与自身相乘时遇到了一个问题:编译器抱怨我不能将该向量借用为可变的,因为它也是借用为不可变的。

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply(&vec);
}
error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
  --> src/main.rs:15:5
   |
15 |     vec.multiply(&vec);
   |     ^^^^--------^----^
   |     |   |        |
   |     |   |        immutable borrow occurs here
   |     |   immutable borrow later used by call
   |     mutable borrow occurs here

这是有道理的,但是将这样的向量与自身相乘的正确方法是什么?更重要的是:对于一般情况,我需要使用自己的方法修改结构,并将相同的结构作为参数。

我想你已经理解了这一点,但你现在所拥有的不起作用的原因是不能在不可变借用的同时可变地借用一个值。要按原样执行该方法,您需要同时使用可变借用(以 &mut self 的形式)和不可变借用(以 other: &Vec2 的形式)。由于您的方法应该适用于 Vec2 的任何两个成员,因此您将始终有两个单独的借用:编译器无法推断出单个借用适用于向量与自身相乘的情况。

对于您的问题,您有多种选择,具体取决于您要执行的操作的详细信息。

选项 1:克隆

只需将 #[derive(Clone)] 添加到 Vec2 的定义中,您就可以使用 clone 方法克隆该类型的元素。

#[derive(Clone)]
struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&mut self, other: &Vec2) {
        self.x *= other.x;
        self.y *= other.y;
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply(&vec.clone());
}

选项 2:复制

如果您的类型如此简单(只有两个浮点数),那么您也可以合理地派生 Copy。然后类型的元素在被提供给函数时被简单地复制,而不需要引用。这意味着我们应该更改 Vec2::multiply 的签名,将 other 简单地视为 Vec2,而不是 &Vec2(这不是绝对必要的,但通常采用指针Copy 类型的效率较低)。

#[derive(Copy, Clone)]
struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&mut self, other: Vec2) {
        self.x *= other.x;
        self.y *= other.y;
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply(vec);
}

选项 3:专用方法

您可以有一个名为 multiply_selfsquare(取决于您的语义)的单独方法,它只需要 &mut self。在使用自身修改结构的一般情况下,这可能是您最好的选择。

struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply_self(&mut self) {
        self.x *= self.x;
        self.y *= self.y;
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply_self();
}

选项 4:return 一个新值

你可以有一个方法,它不会 self 可变,而是 return 一个新的 Vec2。然后你可以做 vec = vec.multiply(&vec).

struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&self, other: &Vec2) -> Vec2 {
        Vec2 {
            x: self.x * other.x,
            y: self.y * other.y,
        }
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec = vec.multiply(&vec)
}

可能还有很多其他方法可以做到这一点,但在这个简单的例子中,我想到了这个。如果您分享更多关于您通常尝试做的事情的细节,我可能会想出更多。