Structs and Impl Blocks
So far the library's data has been loose variables: a title here, a page count there. Real programs group related facts into one named thing. In Rust that thing is a struct, and the error-handling tools later in this section all sit on top of types like it.
The rule
A struct groups named fields; an impl block gives it behaviour.
Define a struct with typed fields:
#[derive(Debug)]
struct Book {
title: String,
pages: u32,
on_loan: bool,
}#[derive(Debug)] lets you print it with {:?}.
Create one by naming every field. If a variable has the same name as a field, write it once (field init shorthand):
let pages = 380;
let book = Book { title: String::from("Iron Tides"), pages, on_loan: false };
println!("{}", book.pages);The whole value is mutable or not; you cannot mark one field mut. Use let mut book to change book.on_loan.
Attach behaviour with impl. Inside, Self is a short name for the type:
impl Book {
fn new(title: &str, pages: u32) -> Self {
Self { title: title.to_string(), pages, on_loan: false }
}
fn is_available(&self) -> bool {
!self.on_loan
}
fn lend(&mut self) {
self.on_loan = true;
}
}
let mut book = Book::new("Iron Tides", 380);
book.lend();
println!("{}", book.is_available()); // falseA type may have several impl blocks, and new is only a naming habit, not a keyword.
Two other shapes exist: tuple structs with unnamed fields, such as struct CardNumber(u32);, useful for giving a plain number its own type; and unit structs with no fields.
The shortcut
Before writing an impl, sort every function into one of three drawers by asking "what does it need from the book?"
Needs no book yet
Creating one:
new. Noself; called asBook::new(...).
The trap is making every method take self by value. The first call would move the book away and the next line would fail to compile.
Drills
Answer fast — trust the rule.
Inside impl Book, what does Self stand for?
How do you make only the on_loan field of a Book mutable?
What does fn is_available(&self) -> bool need from its caller?
What is struct CardNumber(u32);?
Remember
- A struct groups typed, named fields; an impl block adds associated functions and methods.
- No book yet → no
self; read →&self; change →&mut self; consume →self. - Mutability belongs to the whole binding, not to single fields.
