Multiple Implementation Blocks
Part of the Object Oriented Programming section of Coddy's Rust journey — lesson 5 of 61.
Rust allows you to split a struct's methods across multiple impl blocks. While everything could go in a single block, separating them can make your code more organized and readable.
Here's a struct with its functionality split into two implementation blocks:
struct BankAccount {
balance: f64,
}
// Constructor and basic queries
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// Transaction methods
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
Both blocks work together seamlessly—Rust treats them as if they were one. You can call any method regardless of which block it's defined in:
fn main() {
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
}
This pattern becomes especially useful as your structs grow. You might group constructors together, keep read-only methods separate from mutating ones, or organize by feature. There's no limit to how many impl blocks a struct can have.
Challenge
EasyCreate a Player struct with two fields: name (String) and score (u32).
Organize the struct's methods across two separate implementation blocks:
First impl block — Constructor and query:
new— an associated function that takes aname: Stringand returns aPlayerwithscoreset to0get_score— takes&selfand returns the current score asu32
Second impl block — Score modifications:
add_points— takes&mut selfandpoints: u32, adds the points to the scorereset_score— takes&mut selfand sets the score back to0
You will receive three inputs:
- First line: the player's name (String)
- Second line: points to add in the first round (u32)
- Third line: points to add in the second round (u32)
Create a player using Player::new, add the first round points, print the score, then reset the score, add the second round points, and print the final score.
Expected output format:
{score_after_first_round}
{score_after_reset_and_second_round}Cheat sheet
Rust allows splitting a struct's methods across multiple impl blocks for better organization:
struct BankAccount {
balance: f64,
}
// First impl block
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// Second impl block
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
All methods from different impl blocks work together seamlessly:
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
There's no limit to how many impl blocks a struct can have. This pattern is useful for grouping related functionality, such as separating constructors from mutating methods.
Try it yourself
use std::io;
// TODO: Define the Player struct with name (String) and score (u32) fields
// TODO: First impl block - Constructor and query methods (new, get_score)
// TODO: Second impl block - Score modification methods (add_points, reset_score)
fn main() {
let mut input = String::new();
// Read player name
io::stdin().read_line(&mut input).expect("Failed to read line");
let name = input.trim().to_string();
// Read first round points
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let first_round: u32 = input.trim().parse().expect("Invalid number");
// Read second round points
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let second_round: u32 = input.trim().parse().expect("Invalid number");
// TODO: Create a player using Player::new
// TODO: Add first round points and print the score
// TODO: Reset the score
// TODO: Add second round points and print the final score
}This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Methods and Behavior
Intro Implementation BlocksThe Self ParameterMutable MethodsAssociated FunctionsMultiple Implementation BlocksMethod ChainingRecap - Rectangle Actions4Project: Virtual Pet
Defining the PetFeeding the Pet7Standard Traits
The Debug TraitThe Display TraitClone and CopyEquality TraitsRecap - Printable Point10Project: Document System
The Draw TraitText Component2Encapsulation and Modules
Modules BasicsThe Public KeywordPrivate FieldsGettersSettersRecap - Secure Locker5Generics
Generic StructsGeneric MethodsMultiple Generic TypesGeneric FunctionsRecap - Coordinate Point8Traits as Bounds
Trait Bounds SyntaxMultiple BoundsThe Where ClauseReturning Types with TraitsRecap - Generic Printer11Design Patterns in Rust
Newtype PatternCompositionThe Drop TraitFrom and IntoRecap - Smart Pointer Mock