Rust Struct Methods

What are Struct Methods in Rust?

Struct methods are defined within an impl (implementation) block for a struct. These methods can:

  1. Act on the struct’s fields.
  2. Perform operations specific to the struct’s purpose.
  3. Enhance code organization by grouping related functionality.

Types of Struct Methods

Rust supports two types of struct methods:

  1. Instance Methods: Operate on a specific instance of a struct and have access to its fields.
  2. Associated Functions: Methods that do not require an instance of the struct to be called (commonly used as constructors).

Defining and Using Instance Methods

Instance methods are defined with the &self parameter, which allows access to the fields of a struct.

Example:

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

impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}

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

fn main() {
let rect = Rectangle {
width: 10,
height: 20,
};

println!("Area of Rectangle: {}", rect.area());
println!("Is it a square? {}", rect.is_square());
}

Output:

Area of Rectangle: 200
Is it a square? false

Defining and Using Associated Functions

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 {
fn new(width: u32, height: u32) -> Rectangle {
Rectangle { width, height }
}
}

fn main() {
let rect = Rectangle::new(15, 25);
println!("Rectangle dimensions: {} x {}", rect.width, rect.height);
}

Output:

Rectangle dimensions: 15 x 25

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.

Example:

struct Circle {
radius: f64,
}

impl Circle {
fn new(radius: f64) -> Circle {
Circle { radius }
}

fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}

fn circumference(&self) -> f64 {
2.0 * std::f64::consts::PI * self.radius
}
}

fn main() {
let circle = Circle::new(10.0);

println!("Area: {:.2}", circle.area());
println!("Circumference: {:.2}", circle.circumference());
}

Output:

Area: 314.16
Circumference: 62.83

Chaining Methods

Methods can be chained to perform multiple operations in a single expression. This is particularly useful for builder patterns.

Example:

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

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

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

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

fn main() {
let mut point = Point::new(0, 0);
point.move_x(5).move_y(10);

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

Output:

Point: (5, 10)

Method Overloading (Not Supported Directly)

Rust does not support method overloading based on argument types or counts. Instead, you can achieve similar functionality using enums or optional arguments.

Example Using Enums:

struct Shape {
length: u32,
breadth: Option<u32>,
}

impl Shape {
fn area(&self) -> u32 {
match self.breadth {
Some(b) => self.length * b, // Rectangle
None => self.length * self.length, // Square
}
}
}

fn main() {
let square = Shape { length: 10, breadth: None };
let rectangle = Shape { length: 10, breadth: Some(20) };

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

Output:

Square Area: 100
Rectangle Area: 200

Leave a Comment

BoxofLearn