Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. impl / Method Definitions

impl / Method Definitions

Since: Rust 1.0(2015)

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

SignatureDescription
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() -> SelfAn associated function that does not take self (used for constructors and similar).
SelfA type alias referring to the type being implemented. You can use it in place of the type name.

Sample Code

sample_struct_impl_method.rs
#[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 }
    }

    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() {
    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);
}

Compile with the following command:

rustc struct_impl_method.rs
./struct_impl_method
Circle { x: 0.0, y: 0.0, radius: 5.0 }
Area: 78.54
Circumference: 31.42
Contains (3,4)?: true
Contains (4,4)?: false
Circle at (10, 20) with radius 3
Circle { x: 0.0, y: 0.0, radius: 1.0 }

Common Mistakes

Mistake 1: Using &mut self when &self is sufficient

Use &self for methods that do not modify the instance, and &mut self for methods that change fields. Using &mut self on a read-only method forces the caller to declare the instance as mut, which is unnecessarily restrictive.

struct_impl_mistake1.rs
struct Counter {
    count: u32,
}

impl Counter {
    // This only reads data, but uses &mut self unnecessarily.
    fn get_count(&mut self) -> u32 { // unnecessary mut
        self.count
    }
}

fn main() {
    let c = Counter { count: 5 }; // no mut

    // Calling a &mut self method requires the variable to be mut.
    // c.get_count(); // error: c is not declared as mutable
    println!("count: 5");
}

Compile with the following command:

rustc struct_impl_mistake1.rs
./struct_impl_mistake1
count: 5

Use &self for read-only methods.

struct_impl_fix1.rs
struct Counter {
    count: u32,
}

impl Counter {
    // Read-only methods use &self.
    fn get_count(&self) -> u32 {
        self.count
    }

    // Methods that modify state use &mut self.
    fn increment(&mut self) {
        self.count += 1;
    }
}

fn main() {
    let mut c = Counter { count: 0 };
    c.increment();
    c.increment();
    println!("count: {}", c.get_count()); // 2

    // get_count can also be called on an immutable binding.
    let c2 = Counter { count: 10 };
    println!("count: {}", c2.get_count()); // 10
}

Compile with the following command:

rustc struct_impl_fix1.rs
./struct_impl_fix1
count: 2
count: 10

Mistake 2: Using an instance after a method that consumes self

A method that takes self by value (not &self or &mut self) consumes the instance when called. The instance can no longer be used after that point. This pattern is mainly used in the Builder pattern.

struct_impl_mistake2.rs
struct Builder {
    value: i32,
}

impl Builder {
    fn new() -> Self { Builder { value: 0 } }

    // This method consumes self (Builder pattern).
    fn set_value(mut self, v: i32) -> Self {
        self.value = v;
        self
    }

    fn build(self) -> i32 { // Consumes self.
        self.value
    }
}

fn main() {
    let b = Builder::new();
    let result = b.build();

    // build consumed b, so b can no longer be used.
    // b.set_value(5); // compile error: use of moved value `b`
    println!("result: {}", result);
}

Compile with the following command:

rustc struct_impl_mistake2.rs
./struct_impl_mistake2
result: 0

With the Builder pattern, use method chaining.

struct_impl_fix2.rs
struct Builder {
    value: i32,
    label: String,
}

impl Builder {
    fn new() -> Self { Builder { value: 0, label: String::new() } }
    fn set_value(mut self, v: i32) -> Self { self.value = v; self }
    fn set_label(mut self, l: &str) -> Self { self.label = l.to_string(); self }
    fn build(self) -> String { format!("{}={}", self.label, self.value) }
}

fn main() {
    // Use method chaining.
    let result = Builder::new()
        .set_value(42)
        .set_label("score")
        .build();
    println!("{}", result); // score=42
}

Compile with the following command:

rustc struct_impl_fix2.rs
./struct_impl_fix2
score=42

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 .