Structs
⭐️ Structs are used to encapsulate related properties into one unified datatype.
💡 By convention, the name of the struct starts with a capital letter and follows CamelCase.
There are 3 variants of structs, 1. C-like structs
one or more comma separated name:value pairs
brace-enclosed list
similar to classes (without it’s methods) in OOP languages
because fields have names, we can access them through dot notation
Tuple structs
one or more comma separated values
parenthesized list like tuples
looks like a named tuples
Unit structs
a struct with no members at all
it defines a new type but it resembles an empty tuple, ()
rarely in use, useful with generics
⭐️ When regarding OOP in Rust, attributes and methods are placed separately on structs and traits. Structs contain only attributes, traits contain only methods. They are getting connected via impls.
C-like structs
// Struct Declaration
struct Color {
red: u8,
green: u8,
blue: u8
}
fn main() {
// creating an instance
let black = Color {red: 0, green: 0, blue: 0};
// accessing it's fields, using dot notation
println!("Black = rgb({}, {}, {})", black.red, black.green, black.blue); //Black = rgb(0, 0, 0)
// structs are immutable by default, use `mut` to make it mutable but doesn't support field level mutability
let mut link_color = Color {red: 0,green: 0,blue: 255};
link_color.blue = 238;
println!("Link Color = rgb({}, {}, {})", link_color.red, link_color.green, link_color.blue); //Link Color = rgb(0, 0, 238)
// copy elements from another instance
let blue = Color {blue: 255, .. link_color};
println!("Blue = rgb({}, {}, {})", blue.red, blue.green, blue.blue); //Blue = rgb(0, 0, 255)
// destructure the instance using a `let` binding, this will not destruct blue instance
let Color {red: r, green: g, blue: b} = blue;
println!("Blue = rgb({}, {}, {})", r, g, b); //Blue = rgb(0, 0, 255)
// creating an instance via functions & accessing it's fields
let midnightblue = get_midnightblue_color();
println!("Midnight Blue = rgb({}, {}, {})", midnightblue.red, midnightblue.green, midnightblue.blue); //Midnight Blue = rgb(25, 25, 112)
// destructure the instance using a `let` binding
let Color {red: r, green: g, blue: b} = get_midnightblue_color();
println!("Midnight Blue = rgb({}, {}, {})", r, g, b); //Midnight Blue = rgb(25, 25, 112)
}
fn get_midnightblue_color() -> Color {
Color {red: 25, green: 25, blue: 112}
}
Tuple structs
⭐️ When a tuple struct has only one element, we call it new type pattern. Because it helps to create a new type.
struct Color (u8, u8, u8);
struct Kilometers(i32);
fn main() {
// creating an instance
let black = Color (0, 0, 0);
// destructure the instance using a `let` binding, this will not destruct black instance
let Color (r, g, b) = black;
println!("Black = rgb({}, {}, {})", r, g, b); //black = rgb(0, 0, 0);
//newtype pattern
let distance = Kilometers(20);
// destructure the instance using a `let` binding
let Kilometers(distance_in_km) = distance;
println!("The distance: {} km", distance_in_km); //The distance: 20 km
}
Unit structs
This is rarely useful on its own, but in combination with other features, it can become useful.
📖 ex: A library may ask you to create a structure that implements a certain trait to handle events. If you don’t have any data you need to store in the structure, you can create a unit-like struct.
struct Electron;
fn main() {
let x = Electron;
}
Last updated