Rust LogoAn Example Program Using Structs in Rust

In Rust, structs (short for "structures") are custom data types that let you package together related pieces of data. They are similar to classes in object-oriented languages but primarily focus on data aggregation rather than behavior inheritance. Structs are fundamental for creating meaningful and organized data structures in your applications.

Defining a Struct:
A struct is defined using the `struct` keyword, followed by its name (typically `PascalCase`), and then curly braces `{}` containing its fields. Each field has a name and a data type.

Instantiating a Struct:
To create an instance of a struct, you specify the struct's name followed by curly braces, providing values for each field in `field: value` syntax. The order of fields doesn't matter, but all fields must be initialized unless the struct allows for default values (which is often handled with `Default` trait or specific constructors).

Accessing Struct Fields:
You can access individual fields of a struct instance using dot notation (`.`), like `my_struct_instance.field_name`.

Methods and Associated Functions:
Structs can have associated functions and methods defined in an `impl` (implementation) block.
- Methods are functions that are called on an instance of the struct and take `self`, `&self`, or `&mut self` as their first parameter. They operate on the specific data of that instance.
- Associated functions (often used as constructors) are functions that belong to the struct itself, not a particular instance. They are called using `StructName::function_name()`.

Example Program Explanation:
The example program demonstrates how to define a `Book` struct to represent information about a book (title, author, publication year). It then shows how to:
1. Define the `Book` struct with three fields.
2. Implement an associated function `new` to act as a constructor, making it easy to create new `Book` instances.
3. Implement a method `display_details` that takes an immutable reference to `self` (`&self`). This method allows a `Book` instance to print its own details without consuming or mutating the instance.
4. In the `main` function, an instance of `Book` is created using the `Book::new()` associated function, and its `display_details()` method is called to print the book's information.

Example Code

```rust
// 1. Define a struct named 'Book'
// This struct will hold information about a book.
struct Book {
    title: String,
    author: String,
    publication_year: u16,
}

// 2. Implement methods and associated functions for the 'Book' struct
impl Book {
    // Associated function (like a static method or constructor in other languages)
    // 'self' refers to the 'Book' type itself, not an instance.
    // It creates and returns a new Book instance.
    fn new(title: String, author: String, publication_year: u16) -> Book {
        Book {
            title,
            author,
            publication_year,
        }
    }

    // Method (called on an instance of Book)
    // '&self' indicates that this method borrows the Book instance immutably.
    // It can read the instance's data but cannot modify it.
    fn display_details(&self) {
        println!("--- Book Details ---");
        println!("Title: {}", self.title);
        println!("Author: {}", self.author);
        println!("Publication Year: {}", self.publication_year);
        println!("--------------------\n");
    }

    // Another method that takes a mutable reference to self '&mut self'
    // This method can modify the instance's data.
    fn set_publication_year(&mut self, year: u16) {
        self.publication_year = year;
        println!("Updated publication year for '{}' to {}.\n", self.title, self.publication_year);
    }
}

fn main() {
    // 3. Create an instance of the 'Book' struct using the 'new' associated function
    let mut book1 = Book::new(
        String::from("The Rust Programming Language"),
        String::from("Steve Klabnik and Carol Nichols"),
        2018,
    );

    // 4. Call the 'display_details' method on 'book1'
    book1.display_details();

    // Create another book instance
    let mut book2 = Book::new(
        String::from("Effective C++"),
        String::from("Scott Meyers"),
        1991,
    );

    book2.display_details();

    // 5. Demonstrate updating a field using a mutable method
    println!("Changing publication year for book1...");
    book1.set_publication_year(2019);

    // Display details again to show the update
    book1.display_details();
}
```