← 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.
Syntax
rust
impl Name {
    fn method(&self) -> ReturnType {
        // body
    }
}

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
// Define a struct `Rectangle` to group related fields together
struct Rectangle {
    width: f64,
    height: f64,
}

// Implement methods on `Rectangle`
impl Rectangle {
    // Define the function `area` taking `&self` and returning a floating-point number
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `rect`, set to `Rectangle { width: 4.0, height: 3.0 }`
    let rect = Rectangle { width: 4.0, height: 3.0 };
    // Print "Area: {}" to the console, substituting in `rect.area()` (with a trailing newline)
    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
// Define a struct `Rectangle` to group related fields together
struct Rectangle {
    width: f64,
    height: f64,
}

// Implement methods on `Rectangle`
impl Rectangle {
    // Define the function `area` taking `&self` and returning a floating-point number
    fn area(&self) -> f64 {
        self.width * self.height
    }
    // Define the function `perimeter` taking `&self` and returning a floating-point number
    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `rect`, set to `Rectangle { width: 5.0, height: 2.0 }`
    let rect = Rectangle { width: 5.0, height: 2.0 };
    // Print "Area: {}, Perimeter: {}" to the console, substituting in `rect.area(), rect.perimeter()` (with a trailing newline)
    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
// Define a struct `Circle` to group related fields together
struct Circle {
    radius: f64,
}

// Implement methods on `Circle`
impl Circle {
    // Define the function `area` taking `&self` and returning a floating-point number
    fn area(&self) -> f64 {
        3.14159 * self.radius * self.radius
    }
}

// Implement methods on `Circle`
impl Circle {
    // Define the function `diameter` taking `&self` and returning a floating-point number
    fn diameter(&self) -> f64 {
        self.radius * 2.0
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `c`, set to `Circle { radius: 3.0 }`
    let c = Circle { radius: 3.0 };
    // Print "Area: {:.2}, Diameter: {}" to the console, substituting in `c.area(), c.diameter()` (with a trailing newline)
    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
// Define a struct `Rectangle` to group related fields together
struct Rectangle {
    width: f64,
    height: f64,
}

// Implement methods on `Rectangle`
impl Rectangle {
    // Define the function `scaled_area` taking `&self`, `factor` and returning a floating-point number
    fn scaled_area(&self, factor: f64) -> f64 {
        self.width * self.height * factor
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `rect`, set to `Rectangle { width: 2.0, height: 3.0 }`
    let rect = Rectangle { width: 2.0, height: 3.0 };
    // Print "Scaled area: {}" to the console, substituting in `rect.scaled_area(2.0)` (with a trailing newline)
    println!("Scaled area: {}", rect.scaled_area(2.0));
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
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.