When creating custom data structures (precisely called models in software engineering), structs are pretty useful. They are used to store variables that are related. For example, say we want to create a model of a User. We can do so in Rust like this:
struct User {
name: String,
age: i32,
account_balance: f64,
}
This is usually done outside of a function (in global scope) if we intend to use it in more than one place. To use the struct, we must have a method that implements it. A method is a function that is tied to a struct type. Let’s see how to implement methods for a type.
Creating Method Implementations for Structs
Implementing methods for a struct type in Rust allows you to define functions that operate specifically on instances of that struct. This is a powerful feature that promotes encapsulation and enhances code organization. To illustrate, let's build upon the User
struct example and implement some methods.
struct User {
name: String,
age: i32,
account_balance: f64,
}
impl User {
// A method to greet the user
fn greet(&self) {
println!("Hello, my name is {} and I'm {} years old.", self.name, self.age);
}
// A method to deposit money into the user's account
fn deposit(&mut self, amount: f64) {
self.account_balance += amount;
println!("Deposited {:.2} units. New balance: {:.2}", amount, self.account_balance);
}
// A method to check if the user is eligible for a discount
fn is_eligible_for_discount(&self) -> bool {
self.age >= 60 || self.account_balance > 1000.0
}
}
In the example above, we've defined three methods associated with the User
struct. Let's break down how they work:
The
greet
method takes a shared reference (&self
) to aUser
instance and prints a personalized greeting using the user's name and age.The
deposit
method takes a mutable reference (&mut self
) to aUser
instance and anamount
parameter. It adds the specified amount to the user'saccount_balance
and prints out the new balance.The
is_eligible_for_discount
method checks whether the user is eligible for a discount based on age and account balance. It returnstrue
if the user is 60 years or older or their account balance exceeds 1000 units.
Using these methods, you can interact with User
instances more intuitively and structured. Here's an example of how you might use these methods:
fn main() {
let mut user1 = User {
name: String::from("Alice"),
age: 28,
account_balance: 750.0,
};
user1.greet();
user1.deposit(250.0);
if user1.is_eligible_for_discount() {
println!("Congratulations! You are eligible for a discount.");
} else {
println!("Sorry, you are not eligible for a discount.");
}
}
In this way, methods enable you to encapsulate behavior related to a struct and promote cleaner, more readable code. Rust's strict ownership and borrowing rules help ensure that your code remains safe and free from common programming errors.
Note: You can split method implementations into separate modules to make code more readable and accessible.