9.6 Methods and Associated Functions (impl Blocks)

Behavior is added to structs using implementation blocks (impl).

struct Rectangle {
    width: u32,
    height: u32,
}

// Implementation block for Rectangle
impl Rectangle {
    // Associated function (like static method/constructor)
    fn square(size: u32) -> Self {
        Self { width: size, height: size }
    }

    // Method (&self: immutable borrow)
    fn area(&self) -> u32 {
        self.width * self.height
    }

    // Method (&mut self: mutable borrow)
    fn double_width(&mut self) {
        self.width *= 2;
    }

    // Method (self: takes ownership)
    fn describe(self) -> String {
        format!("Rectangle {}x{}", self.width, self.height)
        // `self` is consumed here.
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    let mut rect2 = Rectangle::square(25); // Call associated function

    println!("Area of rect1: {}", rect1.area()); // Call method

    rect2.double_width();
    println!("New width of rect2: {}", rect2.width);

    let description = rect1.describe(); // rect1 is moved and consumed
    println!("Description: {}", description);
    // println!("{}", rect1.width); // Error! `rect1` was moved by `describe`
}

9.6.1 Associated Functions vs. Methods

  • Associated Functions: Do not take self. Called via StructName::function_name(). Used for constructors or type-related utilities.
  • Methods: Take self, &self, or &mut self as the first parameter. Called via instance.method_name(). Operate on an instance.

9.6.2 The self Parameter Variations

  1. &self: Borrows immutably (read-only access to fields).
  2. &mut self: Borrows mutably (read/write access to fields). Requires the instance binding to be mut.
  3. self: Takes ownership (moves the instance into the method). The instance cannot be used afterwards unless returned.

Rust’s method call syntax often handles borrowing/dereferencing automatically (instance.method()).