Lesson 8

Structs

Define custom data types with structs, add methods with impl blocks, and use associated functions.

Defining Structs

Structs let you create custom data types by grouping related values together. Think of them like classes in other languages, but without inheritance. You define a struct with named fields, each with its own type.

struct User {
    name: String,
    age: u32,
}

Methods with impl

To add behavior to a struct, use an impl block. Methods take &self as their first parameter (like this in other languages). Use &self to read, &mut self to modify, or self to consume the struct.

Associated Functions

Functions inside impl that don't take self are called associated functions. They're called with :: syntax, like Rectangle::new(). You'll see these used as constructors all the time in Rust.

Try it

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

impl Rectangle {
    // Associated function (constructor) -- no self parameter
    fn new(width: f64, height: f64) -> Rectangle {
        Rectangle { width, height }
    }

    // Method -- borrows self immutably
    fn area(&self) -> f64 {
        self.width * self.height
    }

    fn is_square(&self) -> bool {
        self.width == self.height
    }

    fn describe(&self) {
        println!(
            "Rectangle: {:.1} x {:.1}, area = {:.1}, square = {}",
            self.width,
            self.height,
            self.area(),
            self.is_square()
        );
    }

    // Method that takes mutable reference
    fn scale(&mut self, factor: f64) {
        self.width *= factor;
        self.height *= factor;
    }
}

fn main() {
    // Create using the associated function
    let mut rect = Rectangle::new(10.0, 5.0);
    rect.describe();

    println!("Area: {:.1}", rect.area());

    // Mutate through a method
    rect.scale(2.0);
    println!("\nAfter scaling by 2x:");
    rect.describe();

    // Create a square
    let square = Rectangle::new(7.0, 7.0);
    square.describe();

    // Direct struct creation also works
    let tiny = Rectangle { width: 1.0, height: 1.0 };
    tiny.describe();
}

Challenge

Add a perimeter() method to the Rectangle struct that returns 2 * (width + height). Call it from main and print the result.

Previous: References & Borrowing

Next: Enums