Я не встречал Self
в документации, только в исходном коде. В документации используется только Self
.
Какая разница между `self` и` Self`?
Ответ 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`
}