Reputation: 3628
What is the difference between a method taking self
and a method taking &self
or even &mut self
?
E.g.
impl SomeStruct {
fn example1(self) { }
fn example2(&self) { }
fn example3(&mut self) { }
}
Say I want to implement a method that pretty prints the struct to stdout, should I take &self
? I guess self
also works? I'm not sure when to use what.
Upvotes: 30
Views: 13236
Reputation: 15878
The other answer is good, but not complete. So, here's more info about self
, &self
and &mut self
.
Short for | Equivalent to | Takes ownership? | When to use? | Example | |
---|---|---|---|---|---|
self |
self: Self |
a: A |
Yes | The code that calls this method should not be able to reuse the object on which you call the method. | Invalidate an object because maybe you transform it into another. Drop an object. Immutable data structures? |
&self |
self: &Self |
a: &A |
No - immutably borrows | For reading self or its fields. |
For printing something or compute a value based on multiple values of other copyable fields. |
&mut self |
self: &mut Self |
a: &mut A |
No - mutable borrows | For reading or writing self and its fields. |
A function that updates the internal state of a data structure. |
mut self |
mut self: Self |
mut a: A |
Yes | If you want to change what self points to. Not useful because it takes ownership. |
Self
is an alias for the type that the impl
block is for.self
as they apply to any other parameter (see e.g. this answer).self
is not just used as the first parameter of a method, but can also be used to reference the current module (more details here).let foo = Foo::new()
(i.e. you cannot mutate foo
) and then you attempt to call a method that requires a mutable reference (i.e. the first parameter is &mut self
), you'll get a compilation error, so you would need to change let foo
to let mut foo
. A complete example is here.Upvotes: 11
Reputation: 170919
From the example in the book (just split onto three separate paragraphs and marked to maybe make it clearer):
&self
: We’ve chosen&self
here for the same reason we used&Rectangle
in the function version: we don’t want to take ownership, and we just want to read the data in the struct, not write to it.
&mut self
: If we wanted to change the instance that we’ve called the method on as part of what the method does, we’d use&mut self
as the first parameter.
self
: Having a method that takes ownership of the instance by using justself
as the first parameter is rare; this technique is usually used when the method transforms self into something else and you want to prevent the caller from using the original instance after the transformation.
Or in other words: the difference is exactly the same as SomeStruct
, &SomeStruct
, and &mut SomeStruct
.
Say I want to implement a method that pretty prints the struct to stdout, should I take
&self
? I guessself
also works?
As you can see, this is exactly a case for &self
. If you use self
(or &mut self
) the method will likely still compile, but it can only be used in more restricted situations.
Upvotes: 26