Defining Structs in Rust
#[derive(Debug)]
struct UserProfile {
username: String,
dimensions: u32,
length: u32,
}
Implementing Struct Methods
impl UserProfile {
// Instance method
fn calculate_area(&self) -> u32 {
self.dimensions * self.length
}
// Method with multiple parameters
fn is_larger_than(&self, other: &UserProfile) -> bool {
self.dimensions > other.dimensions && self.length > other.length
}
// Associated function (static method)
fn create_square(size: u32) -> UserProfile {
UserProfile {
username: String::from(""),
dimensions: size,
length: size
}
}
}
The impl keyword stands for implementation. The Self type is an alias for the type in the impl block. Methods must have a parameter named self of type Self. The &self syntax is shorthand for self: &Self, indicating the method borrows the instance.
To modify the instance in a method, use &mut self as the first parameter instead of &self. Methods with addditional parameters should place them after the self parameter.
Associated functions don't take self as a parameter, so they're not methods but rather associated with the struct type rather than an instance of it.
Using Structs
let user_profile = UserProfile {
username: String::from("rustacean"),
dimensions: 15,
length: 25
};
println!("{:?}", user_profile);
println!("The area of profile {} is {}", user_profile.username, user_profile.calculate_area());
Field Initialization Shorthand
When function parameters have the same name as struct fields, you can use the shorthand syntax:
let profile1 = build_user_profile(String::from("developer"), 12, 18);
println!("{:?}", profile1);
println!("The area of profile {} is {}", profile1.username, profile1.calculate_area());
fn build_user_profile(username: String, width: u32, h: u32) -> UserProfile {
UserProfile { username, width, length: h }
}
Struct Update Syntax
To create a new struct based on an existing one, use the .. syntax:
let profile2 = UserProfile {
username: String::from("engineer"),
..profile1
};
println!("{:?}", profile2);
println!("The area of profile {} is {}", profile2.username, profile2.calculate_area());
The .. syntax indicates that the remaining fields should have the same values as the corresponding fields in the given instance.
Tuple Structs
Tuple structs have unnamed fields but are still distinct types:
struct RGB(u8, u8, u8);
let crimson = RGB(220, 20, 60);
Use tuple structs when you want a simple type with a few eelments but don't need to name each field. The struct name provides meaning to the tuple.
Unit-like Structs
Unit-like structs have no fields and are useful for traits when you don't need to store data:
struct Marker;
let identifier = Marker;
These structs take up no space since they don't have any fields.