为什么不可变特征的实现可以是可变的?

dpr*_*dpr 1 traits ownership mutability rust

这是我的代码,它可以编译

trait AppendBar {
    fn append_bar(self) -> Self;
}

impl AppendBar for Vec<String> {
    fn append_bar(mut self) -> Self {
        self.push("Bar".to_string());
        self
    }

Run Code Online (Sandbox Code Playgroud)

虽然它获取了所有权,但是为什么它可以在实现过程中改变 self 呢?

cdh*_*wie 6

因为参数的可变性不是函数签名的一部分。

这 ...

fn foo(self) { ... }
Run Code Online (Sandbox Code Playgroud)

...从外面看起来和...一模一样

fn foo(mut self) { ... }
Run Code Online (Sandbox Code Playgroud)

...因为一旦控制权转移到函数,参数会发生什么,这不是调用者的事。

因此,允许该特征的实现,因为从调用者的角度来看,签名实际上是相同的。


换句话说,这两个函数有什么区别?

fn foo(mut v: String) {
    // ...
}

fn foo(v: String) {
    let mut v = v; // Rebind v as mutable.
    // ...
}
Run Code Online (Sandbox Code Playgroud)

答案是没有。该String值被赋予了函数,因此它总是可以改变它。如果它可以帮助您理解正在发生的事情,您可以将第一个示例视为第二个示例的“快捷方式”,但它们最终意味着相同的事情。


请注意,这并不是 Rust 独有的事情;在 C++ 中,const函数参数的 -ness 也不是函数签名的一部分。

  • @dpr 是的,因为在这种情况下,它_是_调用者的事;在“&amp;mut”的情况下,函数可以改变它不拥有的值的状态,这是调用者可能需要关心的事情。生命周期也在那里发挥作用。 (4认同)
  • 或者换句话说,“&amp;T”和“&amp;mut T”是不同的_类型_,但“T”和“mut T”只是不同的_绑定模式_。前者对于调用者来说很重要,因为类型必须匹配;后者不是,因为绑定模式可以自由更改 (3认同)