C.W.K.
Stream
Lesson 04 of 05 · published

Methods & Associated Functions

~11 min · types, methods, impl, self

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

A struct holds data; an impl block attaches behavior. This is where the self parameter — and the ownership rules you already know — show up in method form.

The impl block

You define methods inside impl TypeName { ... }. A method's first parameter is a form of self, and which form you choose says exactly what the method does with the instance: borrow it, mutate it, or consume it.

The three selfs

&self borrows the instance to read it — the default for most methods. &mut self borrows it to modify it in place. Plain self consumes the instance (takes ownership), used when a method transforms a value into something else and the original shouldn't survive. The borrowing rules you learned apply directly: &self is an immutable borrow, &mut self a mutable one.

The form of self is the method's contract. &self = 'I'll read.' &mut self = 'I'll change you.' self = 'I'll consume you.' A reader sees the method signature and knows immediately what it does to the receiver — no guessing.

Associated functions

A function in an impl block with no self is an associated function, called with ::. The universal example is a constructor: by convention you write fn new(...) -> Self and call it Point::new(1, 2). Self (capital S) is shorthand for the type the impl is on.

Code

Constructor, read method, and mutating method·rust
#[derive(Debug)]
struct Rect { w: u32, h: u32 }

impl Rect {
    // associated function (constructor) — no self, called with ::
    fn new(w: u32, h: u32) -> Self {
        Self { w, h }
    }
    // &self: borrow to read
    fn area(&self) -> u32 {
        self.w * self.h
    }
    // &mut self: borrow to modify in place
    fn scale(&mut self, factor: u32) {
        self.w *= factor;
        self.h *= factor;
    }
}

fn main() {
    let mut r = Rect::new(3, 4); // associated function
    println!("area = {}", r.area()); // method
    r.scale(2);
    println!("{r:?} area = {}", r.area());
}

External links

Exercise

Give the Rect struct a new constructor, an area(&self) method, and a square(size: u32) -> Self associated function that builds a square. Call all three. Why can area be called on an immutable Rect but scale requires mut?
Hint
area takes &self (an immutable borrow), so it works on any Rect. scale takes &mut self, which requires the binding to be mut — the same aliasing rule, expressed through the method's self form.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.