impl / Method Definitions
In Rust, you add methods to a struct using an impl block. You can define two kinds of functions: instance methods that take &self, and associated functions that do not take self (such as constructors).
Syntax
struct Rectangle {
width: f64,
height: f64,
}
impl Rectangle {
// Associated function (constructor): does not take self.
fn new(width: f64, height: f64) -> Self {
Rectangle { width, height }
}
// Instance method: takes &self as an immutable reference.
fn area(&self) -> f64 {
self.width * self.height
}
// Takes &mut self as a mutable reference to modify fields.
fn scale(&mut self, factor: f64) {
self.width *= factor;
self.height *= factor;
}
}
// How to call them.
let mut r = Rectangle::new(5.0, 3.0); // Call associated functions with ::.
println!("{}", r.area()); // Call methods with ..
r.scale(2.0);
Method Types
| Signature | Description |
|---|---|
| fn method(&self) | An instance method that takes an immutable reference. |
| fn method(&mut self) | An instance method that takes a mutable reference (allows modifying fields). |
| fn method(self) | A method that takes ownership (the instance cannot be used after the call). |
| fn func() -> Self | An associated function that does not take self (used for constructors and similar). |
| Self | A type alias referring to the type being implemented. You can use it in place of the type name. |
Sample Code
#[derive(Debug)]
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
// Associated function (constructor).
fn new(x: f64, y: f64, radius: f64) -> Self {
Circle { x, y, radius }
}
// Factory function that creates a circle centered at the origin.
fn at_origin(radius: f64) -> Self {
Circle::new(0.0, 0.0, radius)
}
// &self: read-only method.
fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}
fn circumference(&self) -> f64 {
2.0 * std::f64::consts::PI * self.radius
}
fn contains(&self, x: f64, y: f64) -> bool {
let dx = self.x - x;
let dy = self.y - y;
(dx * dx + dy * dy).sqrt() <= self.radius
}
// &mut self: method that modifies fields.
fn move_to(&mut self, x: f64, y: f64) {
self.x = x;
self.y = y;
}
fn resize(&mut self, new_radius: f64) {
self.radius = new_radius;
}
}
// You can split impl blocks across multiple blocks.
impl Circle {
fn description(&self) -> String {
format!(
"Circle at ({}, {}) with radius {}",
self.x, self.y, self.radius
)
}
}
fn main() {
// Create an instance using an associated function.
let mut c = Circle::new(0.0, 0.0, 5.0);
println!("{:?}", c);
// Call methods.
println!("Area: {:.2}", c.area());
println!("Circumference: {:.2}", c.circumference());
println!("Contains (3,4)?: {}", c.contains(3.0, 4.0)); // true (distance = 5)
println!("Contains (4,4)?: {}", c.contains(4.0, 4.0)); // false (distance ≈ 5.65)
// Modify state with a &mut self method.
c.move_to(10.0, 20.0);
c.resize(3.0);
println!("{}", c.description());
// Another constructor.
let c2 = Circle::at_origin(1.0);
println!("{:?}", c2);
}
Notes
Methods in Rust are defined inside an impl block. You can write multiple impl blocks for the same type, which lets you organize related functionality into separate sections.
Associated functions are called with :: on the type name (e.g., Circle::new()). Rust has no special constructor syntax; by convention, you use an associated function named new().
For struct field definitions, see struct / Field Definition. For implementing traits, see trait / impl Trait for Type.
If you find any errors or copyright issues, please contact us.