A method in Rust is a function defined inside an impl block for a struct. It operates on an instance of the struct using self. An associated function is similar, but it does not take self and is often used as a constructor or helper.
Once you start working with structs, you will want to attach behavior to them. Rust lets you do this using methods and associated functions. This is similar to how JavaScript lets you add methods to objects or classes.
In this post, I will show you how to write methods that work with struct instances, how to use self, and how to define functions that belong to a type but do not require an instance.
If you have not yet read Structs in Rust, that is a must-read before starting here.
What is an impl Block?
An impl block (short for “implementation”) is where you define methods for a struct.
Example
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
Here, area is a method that takes a reference to self and returns the area.
Calling a Method
You call methods using dot syntax:
let rect = Rectangle { width: 10, height: 5 };
println!("Area is {}", rect.area());
Rust automatically adds & for &self, so you do not need to call rect.area(&rect).
Self and Mutability
There are three ways to define self in a method:
- &self — read-only access
- &mut self — allows mutation
- self — takes ownership
Example using &mut self:
impl Rectangle {
fn double_width(&mut self) {
self.width *= 2;
}
}
Then call it like this:
let mut rect = Rectangle { width: 10, height: 5 };
rect.double_width();
Note: you must make the instance mut to call methods with &mut self.
Associated Functions
Associated functions are functions that belong to a type but do not need an instance. These do not take self.
impl Rectangle {
fn new(width: u32, height: u32) -> Rectangle {
Rectangle { width, height }
}
}
Call them like this:
let rect = Rectangle::new(10, 5);
This is like a constructor. You can have multiple associated functions to build your type in different ways.
Multiple impl Blocks
You can split methods across different impl blocks if needed:
impl Rectangle {
fn width(&self) -> u32 {
self.width
}
}
impl Rectangle {
fn height(&self) -> u32 {
self.height
}
}
This helps when organizing large files or adding features gradually.
Method Chaining
If your methods return self, you can chain them:
impl Rectangle {
fn set_width(mut self, width: u32) -> Self {
self.width = width;
self
}
fn set_height(mut self, height: u32) -> Self {
self.height = height;
self
}
}
let rect = Rectangle { width: 0, height: 0 }
.set_width(10)
.set_height(5);
This style is helpful for builder patterns or configuration.
Summary
Rust allows you to define methods that operate on struct instances using impl blocks and self. You can also define associated functions that act like constructors. These patterns bring structure and behavior together, making your code easier to read and extend.