tezvyn:

Rust Methods: Attaching Behavior to Data

AI-drafted, machine-checkedSource: doc.rust-lang.orgintermediate

Rust methods are functions attached to your data structures, defined in an `impl` block. Instead of `do_thing(my_struct)`, you call `my_struct.do_thing()`. The key footgun: `instance.name()` calls a method, but `instance.name` accesses a field.

WHY IT EXISTS: To solve code organization. Instead of scattering functions that operate on a data type throughout a codebase, methods group all related behaviors directly with the data type itself inside an impl block. This makes the capabilities of a type easy to discover and manage.

THE MENTAL MODEL: Think of methods as verbs for your nouns (structs). If a Rectangle struct is your data, its area() method is an action it can perform. Methods are defined in an impl (implementation) block, formally tying the behavior to the data structure it operates on.

HOW IT WORKS: Methods are functions defined inside an impl block whose first parameter is self, representing the instance of the type. This parameter specifies ownership: &self borrows immutably for reading, &mut self borrows mutably for modification, and self takes ownership, consuming the instance. When you call my_instance.my_method(), Rust automatically passes the instance as the first argument, a convenience known as method syntax. The type Self (with a capital S) inside an impl block is an alias for the type the block is for, so &self is shorthand for self: &Self.

WHEN TO USE IT: This is the idiomatic way to define behavior on structs and enums in Rust. Use methods to encapsulate logic that operates on an instance of a type. This leads to cleaner, more organized code compared to using standalone functions; for example, rect.area() is preferred over area(rect).

WHEN NOT TO USE IT: While methods are the default, a standalone function is better for logic that isn't tied to a single instance's state. If a function is a generic utility or operates on multiple unrelated types, it doesn't belong in an impl block for one specific type. Functions within an impl block that do not take self as a parameter are called associated functions, often used as constructors like String::new().

ONE CANONICAL EXAMPLE: Given a struct Rectangle { width: u32, height: u32 }, you can define a method in an impl Rectangle block: fn area(&self) -> u32 { self.width * self.height }. This is called on an instance like let my_rect = Rectangle { ... }; let a = my_rect.area();. A common footgun is name collision. You could also have a method fn width(&self) -> bool { self.width > 0 }. Rust distinguishes by syntax: my_rect.width() calls the method, while my_rect.width accesses the field.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.