Methods and self
self is just how the method refers to the very struct it's attached to.In this page:
impl Name {
fn read(&self) {}
fn modify(&mut self) {}
fn consume(self) {}
}
Reading Data with &self
A method that only needs to read the struct's fields takes &self, an immutable borrow of the instance. This is the most common kind of method.
Example: Reading Data with &self
// Define a struct `Book` to group related fields together
struct Book {
title: String,
pages: u32,
}
// Implement methods on `Book`
impl Book {
// Define the function `summary` taking `&self` and returning a String
fn summary(&self) -> String {
format!("{} ({} pages)", self.title, self.pages)
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `book`, set to `Book { title: String::from("The Rust Book"), pages: 500 }`
let book = Book { title: String::from("The Rust Book"), pages: 500 };
// Print "{}" to the console, substituting in `book.summary()` (with a trailing newline)
println!("{}", book.summary());
}
Login to try C/C++/Java/PHP code in the editor
Modifying Data with &mut self
A method that changes one of the struct's fields must take &mut self, a mutable borrow, and the variable holding the instance must itself be declared mut.
Example: Modifying Data with &mut self
// Define a struct `Counter` to group related fields together
struct Counter {
value: i32,
}
// Implement methods on `Counter`
impl Counter {
// Define the function `increment` taking `self`
fn increment(&mut self) {
self.value += 1;
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare a mutable variable `counter`, initialized to `Counter { value: 0 }`
let mut counter = Counter { value: 0 };
counter.increment();
counter.increment();
// Print "Counter: {}" to the console, substituting in `counter.value` (with a trailing newline)
println!("Counter: {}", counter.value);
}
Login to try C/C++/Java/PHP code in the editor
Consuming self
A method that takes plain self (no &) takes full ownership of the instance, consuming it. This is used when a method transforms a value into something else and the original should no longer be usable.
Example: Consuming self
// Define a struct `Wrapper` to group related fields together
struct Wrapper {
value: String,
}
// Implement methods on `Wrapper`
impl Wrapper {
// Define the function `unwrap` taking `self` and returning a String
fn unwrap(self) -> String {
self.value
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `wrapped`, set to `Wrapper { value: String::from("inside") }`
let wrapped = Wrapper { value: String::from("inside") };
// Declare an immutable variable `inner`, set to `wrapped.unwrap()`
let inner = wrapped.unwrap();
// Print "{}" to the console, substituting in `inner` (with a trailing newline)
println!("{}", inner);
}
Login to try C/C++/Java/PHP code in the editor
Dot Syntax Handles Referencing Automatically
When you call instance.method(), Rust automatically inserts the right amount of referencing or dereferencing to match what the method's self parameter expects, so you rarely need to write (&instance).method() manually.
Example: Dot Syntax Handles Referencing Automatically
// Define a struct `Temperature` to group related fields together
struct Temperature {
celsius: f64,
}
// Implement methods on `Temperature`
impl Temperature {
// Define the function `to_fahrenheit` taking `&self` and returning a floating-point number
fn to_fahrenheit(&self) -> f64 {
self.celsius * 9.0 / 5.0 + 32.0
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `temp`, set to `Temperature { celsius: 20.0 }`
let temp = Temperature { celsius: 20.0 };
// Print "{}F" to the console, substituting in `temp.to_fahrenheit()` (with a trailing newline)
println!("{}F", temp.to_fahrenheit());
}
Login to try C/C++/Java/PHP code in the editor
- Writing
selfwhen you meant&self, which would move the struct into the method instead of just borrowing it. - Forgetting
&mut selfis required for any method that modifies one of the struct's own fields. - Calling a method as
Type::method(instance)when the simplerinstance.method()dot-call syntax is clearer and idiomatic.
&selfborrows the instance immutably, letting a method read its fields without taking ownership.&mut selfborrows the instance mutably, letting a method modify its fields.- Plain
self(without&) takes ownership of the instance, consuming it -- used less often, typically for conversions. - Dot-call syntax
instance.method()automatically handles referencing/dereferencingselffor you.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: