What are Struct Methods in Rust?

Struct methods are defined within an impl (implementation) block for a struct. These methods can do multiple things, like:

  1. You define them inside an impl block for the struct.
  2. These methods can use the data inside the struct to calculate, modify, display values, etc.
  3. They help keep related code together, making your program more organized and easier to understand.

Types of Struct Methods In Rust

Rust supports two types of struct methods:

  1. Instance Methods
  2. Associated Functions

How To Use Instance Methods In Rust?

This method works with a specific instance of a struct. It has access to the struct’s fields through the &self parameter, and you call them on an object of the struct.

Example:

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

impl Rectangle {
// Calculates area using the fields of this rectangle
fn area(&self) -> u32 {
self.width * self.height
}

// Checks if rectangle is a square
fn is_square(&self) -> bool {
self.width == self.height
}
}

fn main() {
let rect = Rectangle { width: 10, height: 20 };
println!("Area: {}", rect.area()); // Uses rect’s fields
println!("Is square? {}", rect.is_square());
}

Output:

Area: 200
Is square? false
  • rect.area() reads width and height to calculate the area.
  • rect.is_square() checks if width and height are equal. You need an instance (rect) to use these methods.

How To Use Associated Functions In Rust?

Associated functions do not have a self parameter and are typically used as constructors or utility functions.

Example:

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

impl Rectangle {
// Creates a new rectangle instance
fn new(width: u32, height: u32) -> Rectangle {
Rectangle { width, height }
}
}

fn main() {
let rect = Rectangle::new(15, 25); // No object needed to call new()
println!("Dimensions: {} x {}", rect.width, rect.height);
}

Output:

Dimensions: 15 x 25
  • Rectangle::new(15, 25) creates a new Rectangle. You don’t need an existing object to call an associated function.

Combining Instance Methods and Associated Functions

You can define both types of methods in the same impl block to provide complete functionality for the struct.

For example:

struct Circle {
radius: f64,
}

impl Circle {
// Create a new circle (associated function)
fn create(radius: f64) -> Circle {
Circle { radius }
}

// Calculate area of the circle (instance method)
fn calculate_area(&self) -> f64 {
3.14159 * self.radius * self.radius
}

// Calculate circumference of the circle (instance method)
fn calculate_circumference(&self) -> f64 {
2.0 * 3.14159 * self.radius
}
}

fn main() {
let my_circle = Circle::create(10.0);

println!("Area: {:.2}", my_circle.calculate_area());
println!("Circumference: {:.2}", my_circle.calculate_circumference());
}

Output:

Area: 314.16
Circumference: 62.83

What Is Chaining Methods In Rust?

The Chaining Method is a technique where you call multiple methods on the same object in a single line. Instead of writing each method call on a separate line, you “chain” them together because each method returns the object itself (or a reference to it).

For example:

struct Point {
x: i32,
y: i32,
}

impl Point {
fn new(x: i32, y: i32) -> Point {
Point { x, y }
}

fn move_x(&mut self, dx: i32) -> &mut Self {
self.x += dx;
self
}

fn move_y(&mut self, dy: i32) -> &mut Self {
self.y += dy;
self
}
}

fn main() {
let mut p = Point::new(0, 0);
p.move_x(5).move_y(10); // Chaining methods

println!("Point: ({}, {})", p.x, p.y);
}

Output:

Point: (5, 10)

Method Overloading (Not Supported Directly)

Method overloading is when you create multiple methods with the same name but different arguments (like in Java or C++). You cannot define two methods with the same name but different parameters.

Example Using Enums:

struct BoxShape {
width: u32,
height: Option<u32>, // Optional for square or rectangle
}

impl BoxShape {
fn area(&self) -> u32 {
match self.height {
Some(h) => self.width * h, // Rectangle area
None => self.width * self.width, // Square area
}
}
}

fn main() {
let square = BoxShape { width: 12, height: None };
let rectangle = BoxShape { width: 12, height: Some(8) };

println!("Square Area: {}", square.area());
println!("Rectangle Area: {}", rectangle.area());
}

Output:

Square Area: 144
Rectangle Area: 96

In the code above:

  • If height is None, treat it as a square.
  • If height is Some(value), treat it as a rectangle.

Learn More About Rust Programming

Leave a Comment