← Back to Rust Course | Chapter 7: Structs | Lesson 2 of 7

impl Blocks

An impl block is where you teach a struct how to do things, by writing functions that belong to it.

Defining an impl Block

An impl block associates functions with a specific struct, letting you group behavior together with the data it operates on rather than scattering unrelated free functions.

Example: Defining an impl Block

markup
struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
    let rect = Rectangle { width: 4.0, height: 3.0 };
    println!("Area: {}", rect.area());
}

Multiple Methods in One impl Block

A single impl block can define as many methods as needed, each becoming callable on any instance of that struct using dot notation.

Example: Multiple Methods in One impl Block

markup
struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }
}

fn main() {
    let rect = Rectangle { width: 5.0, height: 2.0 };
    println!("Area: {}, Perimeter: {}", rect.area(), rect.perimeter());
}

Multiple impl Blocks for the Same Struct

Rust allows splitting a struct's behavior across several impl blocks; they are merged together by the compiler, which can be useful for organizing large amounts of functionality.

Example: Multiple impl Blocks for the Same Struct

markup
struct Circle {
    radius: f64,
}

impl Circle {
    fn area(&self) -> f64 {
        3.14159 * self.radius * self.radius
    }
}

impl Circle {
    fn diameter(&self) -> f64 {
        self.radius * 2.0
    }
}

fn main() {
    let c = Circle { radius: 3.0 };
    println!("Area: {:.2}, Diameter: {}", c.area(), c.diameter());
}

Methods Can Take Extra Parameters

Beyond self, methods can accept additional parameters just like regular functions, allowing them to compute results based on outside input as well as the struct's own data.

Example: Methods Can Take Extra Parameters

markup
struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    fn scaled_area(&self, factor: f64) -> f64 {
        self.width * self.height * factor
    }
}

fn main() {
    let rect = Rectangle { width: 2.0, height: 3.0 };
    println!("Scaled area: {}", rect.scaled_area(2.0));
}
Common Mistakes
  1. Writing free-standing functions that take a struct as their first argument instead of grouping them into an impl block.
  2. Forgetting that a struct can have multiple impl blocks -- Rust allows splitting them for organization.
  3. Confusing methods (which take self) with associated functions (which don't) when writing them inside the same impl block.
Chapter Summary
  • impl TypeName { ... } associates functions with a particular struct type.
  • Functions inside an impl block that take self as their first parameter are called methods.
  • A struct can have more than one impl block; Rust merges them together.
  • Grouping behavior in impl blocks keeps related logic organized next to the data it operates on.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.