Lesson 11 / 25
Structs and impl Blocks
Data with methods.
&self, &mut self, Self
A struct groups named fields; an impl block adds methods and associated functions. A method's receiver says how it uses the value: &self reads, &mut self modifies, self consumes. Associated functions without self (like Account::new) act as constructors. #[derive(Debug, Clone, PartialEq)] asks the compiler to generate common trait implementations: debug printing with {:?}, cloning and equality.
Model data and behaviour precisely
Structs hold data, enums model alternatives, and traits define shared behaviour.
An account with a constructor and methods, run
I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). new builds the struct, deposit takes &mut self, summary takes &self, and derived traits give debug printing, cloning and ==.
#[derive(Debug, Clone, PartialEq)]
struct Account {
owner: String,
balance: u64,
}
impl Account {
fn new(owner: &str) -> Self {
Self { owner: owner.to_string(), balance: 0 }
}
fn deposit(&mut self, amount: u64) {
self.balance += amount;
}
fn summary(&self) -> String {
format!("{} has {}", self.owner, self.balance)
}
}
fn main() {
let mut acc = Account::new("Asha");
acc.deposit(150);
println!("{}", acc.summary());
println!("{acc:?}");
let other = acc.clone();
println!("equal: {}", acc == other);
}
Output:
Asha has 150
Account { owner: "Asha", balance: 150 }
equal: trueDerive what you need
Deriving Debug on most types makes logging and debugging much easier.
Quick check: Which receiver lets a method modify the struct?
- static self
- &self
- Self
- &mut self
Answer
&mut self — Mutation needs an exclusive borrow.