Подтвердить что ты не робот

Какая разница между `self` и` Self`?

Я не встречал Self в документации, только в исходном коде. В документации используется только Self.

4b9b3361

Ответ 1

self, когда используется в качестве аргумента первого метода, является сокращением для self: Self - также существует &self, которое равно self: &Self и &mut self, которое равно self: &mut Self.

self в аргументах метода - синтаксический сахар для типа приема метода (т.е. тип, в котором impl этот метод включен. Это также позволяет использовать нестандартные типы без слишком большого повторения.

Ответ 2

Self - тип текущего объекта. Он может появляться либо в формате trait, либо impl, но чаще всего встречается в trait, где он представляет собой stand-in для любого типа, который завершит реализацию 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 shorter after all!
    fn clone(&self) -> Self;
}

Я мог бы также использовать его в регулярном impl, если я ленивый (это короче!):

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

Self - это имя, используемое в trait или impl для первого аргумента метода. Использование другого имени возможно, однако есть заметная разница:

  • если используется Self, введенная функция представляет собой метод
  • если используется любое другое имя, введенная функция является связанной функцией

В 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) { ... }
}

Таким образом, таблица соответствия:

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`
}