What's the difference between self and Self?

I haven't come across Self in the documentation, only in the source code. The documentation only uses self.

32505 次浏览

当使用 self作为第一个方法参数时,它是 self: Self的简写。还有相当于 self: &Self&self和相当于 self: &mut Self&mut self

方法参数中的 Self是方法接收类型的 语法糖(也就是说,这个方法所在的 impl类型)。这也允许泛型类型没有太多的重复。

Self 是当前对象的类型。它可能出现在 traitimpl中,但最常出现在 trait中,它是最终实现 trait的任何类型的替身(在定义 trait时这是未知的) :

trait Clone {
fn clone(&self) -> Self;
}

如果我实现 Clone:

impl Clone for MyType {
// I can use either the concrete type (known here)
fn clone(&self) -> MyType;


// Or I can use Self again, it's shorter after all!
fn clone(&self) -> Self;
}

如果我很懒,我也可以在常规的 impl中使用它(它更短!) :

impl MySuperLongType {
fn new(a: u32) -> Self { ... }
}

self是方法的第一个参数在 traitimpl中使用的名称。使用另一个名字是可能的,但是有一个显著的区别:

  • if using self, the function introduced is a method
  • if using any other name, the function introduced is an associated function

在 Rust 中,没有隐式的 this参数传递给类型的方法: 您必须显式地将“当前对象”作为方法参数传递。这将导致:

impl MyType {
fn doit(this: &MyType, a: u32) { ... }
}

正如我们已经看到的,作为一个较短的形式,这也可以是(仍然冗长) :

impl MyType {
fn doit(this: &Self, a: u32) { ... }
}

这实际上就是 &self归结起来的内容。

impl MyType {
fn doit(&self, a: u32) { ... }
}

Thus the correspondence table:

self => self: Self
&self => self: &Self
&mut self => self: &mut Self

然而,调用这些函数的方式发生了变化:

impl MyType {
fn doit(&self, a: u32) {
// ...
}
fn another(this: &Self, a: u32) {
// ...
}
}


fn main() {
let m = MyType;


// Both can be used as an associated function
MyType::doit(&m, 1);
MyType::another(&m, 2);


// But only `doit` can be used in method position
m.doit(3);     // OK: `m` is automatically borrowed
m.another(4);  // ERROR: no method named `another`
}

Self引用实现 trait 的当前类型,而 self引用实例。

使用 self作为第一个参数是生锈定义方法的方式。它只是一个将函数转换为方法的约定,就像在 python 中一样。在功能上,self类似于 JavaScript 中的 this

对于那些不知道函数和方法之间区别的人来说,方法是附加到实例并通过该实例调用的函数。