---
title: "10.x Chapter 10 summary and quiz"
description: "Review of structs, methods, associated functions, deriving Debug, and ownership in structs, with a chapter quiz and a capstone program."
url: "https://learnrust.net/chapter-10/chapter-10-summary-and-quiz/"
last_updated: "2026-06-13"
---

# 10.x Chapter 10 summary and quiz

This chapter handed you the first half of the type-building toolkit. Quick review, then a quiz that builds a small type from scratch.

## Quick review

A **struct** is a program-defined type that groups related values under one name ([10.1](https://learnrust.net/chapter-10/introduction-to-program-defined-types/)). Types are named in `UpperCamelCase`, fields in `snake_case`, and the lints enforce it. A struct answers "what parts make up this thing?"; chapter 11's enums answer "which of these things is it?"

You define a struct with named fields and create an **instance** by giving *every* field a value; leaving one out is E0063, because a half-built value is uninitialized ([10.2](https://learnrust.net/chapter-10/defining-and-instantiating-structs/)). Read and write fields with dot notation. Mutability attaches to the binding, not the field: there's no per-field `mut`, so the whole instance is mutable or none of it is. Two pieces of syntax cut the repetition ([10.3](https://learnrust.net/chapter-10/field-init-and-update-syntax/)): **field init shorthand** writes `name` for `name: name` when a variable matches, and **struct update syntax** (`..base`) fills remaining fields from another instance, moving (or copying) them per chapter 8's rules.

Beyond named-field structs there are **tuple structs** (`struct Rgb(u8, u8, u8)`), whose fields are positional, and **unit structs** (`struct Marker;`), which hold no data ([10.4](https://learnrust.net/chapter-10/tuple-structs-and-unit-structs/)). A single-field tuple struct is the **newtype pattern**: wrapping a value to give it a distinct type, turning "this `f64` is meters" from a comment into a compiler check.

A **method** is a function defined in an **`impl` block** that takes `self` and is called with a dot ([10.5](https://learnrust.net/chapter-10/methods-and-impl-blocks/)). The receiver is the chapter 9 parameter decision once more: `&self` to read, `&mut self` to modify in place, `self` to consume. An **associated function** has no `self` and is called on the type with `::` ([10.6](https://learnrust.net/chapter-10/associated-functions-and-constructors/)). Rust has no constructors; `::new` is just an associated function named by convention that returns a fresh instance, and `#[derive(Default)]` supplies a `::default()` that zeroes every field.

A struct can't be printed with `{}` until you implement `Display` yourself (chapter 16), but `#[derive(Debug)]` enables `{:?}` and the pretty `{:#?}` for free ([10.7](https://learnrust.net/chapter-10/deriving-debug/)). `derive` is the compiler writing obvious boilerplate; each name in the list is a **trait**, chapter 16's subject. Finally, a struct **owns its fields** ([10.8](https://learnrust.net/chapter-10/ownership-in-structs/)): moving the struct moves them all, dropping it drops them all, and it's `Copy` only if every field is. Storing a reference in a struct needs a **lifetime** (E0106), which is why your structs hold owned fields like `String` until chapter 17. The rectangle project ([10.9](https://learnrust.net/chapter-10/project-rectangles/)) walked the whole thing from loose variables to a type with methods.

## Quiz time

**Question #1**

From memory: what's the difference between a method and an associated function, and how is each called?

<details class="solution">
<summary>Show solution</summary>

A method takes `self` (as `&self`, `&mut self`, or `self`) and is called on an instance with a dot: `r.area()`. An associated function takes no `self` and is called on the type with a path: `Rectangle::new(...)`. Both live in `impl` blocks and belong to the type.

</details>

**Question #2**

Compiles or not? For each failure, name the cause.

a)

```rust
struct Point { x: f64, y: f64 }
fn main() {
    let p = Point { x: 1.0 };
    println!("{}", p.x);
}
```

b)

```rust
#[derive(Debug)]
struct P { x: f64 }
fn main() {
    let p = P { x: 1.0 };
    println!("{:?}", p);
}
```

c)

```rust
struct P { x: f64 }
fn main() {
    let p = P { x: 1.0 };
    p.x = 2.0;
    println!("{}", p.x);
}
```

d)

```rust
#[derive(Debug)]
struct Note { body: String }
fn main() {
    let a = Note { body: String::from("hi") };
    let b = a;
    println!("{:?} {:?}", a, b);
}
```

<details class="solution">
<summary>Show solution</summary>

a) Refused, E0063: missing field `y`. Every field must be initialized. b) Compiles, prints `P { x: 1.0 }`. c) Refused, E0594: `p` isn't `mut`, so its field can't be assigned. d) Refused, E0382: `let b = a;` moves `a` (a `Note` holds a `String`, so it isn't `Copy`), and `a` is then read after the move. Fix with `&a` or `a.clone()` (after deriving `Clone`).

</details>

**Question #3**

Choose the receiver (`&self`, `&mut self`, `self`) or "associated function (no self)" for each:

a) `Circle::unit()` returning a circle of radius 1
b) a method returning the circle's circumference
c) a method that grows the radius by a given amount
d) a method that consumes the circle and returns its area, discarding the circle

<details class="solution">
<summary>Show solution</summary>

a) Associated function, no `self`: it builds a new instance. b) `&self`: reads only. c) `&mut self`: changes a field in place. d) `self`: consumes the instance (the circle is thrown away).

</details>

**Question #4**

The capstone. Define a `BankAccount` struct with an `owner: String` and a `balance: u64` (cents, the lesson [6.x](https://learnrust.net/chapter-6/chapter-6-summary-and-quiz/) "count money in integer cents" rule). Give it: an associated function `new(owner: String) -> BankAccount` starting at zero balance; a `deposit(&mut self, cents: u64)` method; a `withdraw(&mut self, cents: u64)` method that only subtracts if the balance is sufficient (otherwise leaves it unchanged); and a `summary(&self) -> String` returning something like `"Ada: 1250 cents"`. Derive `Debug`. In `main`, open an account, deposit 2000, withdraw 750, attempt to withdraw 9999 (should be refused), and print the summary.

<details class="solution">
<summary>Show solution</summary>

```rust
#[derive(Debug)]
struct BankAccount {
    owner: String,
    balance: u64,
}

impl BankAccount {
    fn new(owner: String) -> BankAccount {
        BankAccount { owner, balance: 0 }
    }

    fn deposit(&mut self, cents: u64) {
        self.balance += cents;
    }

    fn withdraw(&mut self, cents: u64) {
        if cents <= self.balance {
            self.balance -= cents;
        }
    }

    fn summary(&self) -> String {
        format!("{}: {} cents", self.owner, self.balance)
    }
}

fn main() {
    let mut account = BankAccount::new(String::from("Ada"));
    account.deposit(2000);
    account.withdraw(750);
    account.withdraw(9999);   // refused: balance unchanged
    println!("{}", account.summary());
}
```

```
Ada: 1250 cents
```

Design notes. `new` is an associated function (no `self`) using field init shorthand for `owner`. `deposit` and `withdraw` take `&mut self` because they change the balance, so `account` must be a `mut` binding. `withdraw` guards with `if cents <= self.balance`, so the 9999 attempt does nothing rather than underflowing a `u64` (which would panic in debug, lesson [4.4](https://learnrust.net/chapter-4/integer-overflow/)). `summary` takes `&self` and uses `format!` (lesson [5.5](https://learnrust.net/chapter-5/formatting-strings/)) to build an owned `String`. The whole type owns its data, so it could move into a function or a collection without dragging a lifetime along.

If you reached for `f64` to hold dollars, reread lesson [6.x](https://learnrust.net/chapter-6/chapter-6-summary-and-quiz/): money in floats accumulates rounding error (lesson [4.5](https://learnrust.net/chapter-4/floating-point-types/)). Integer cents is the rule.

</details>

You can now invent types whose parts coexist. Chapter 11 gives you the other kind: enums, where a value is exactly *one of* several alternatives, where `Option` retires the null-pointer mistake, and where `match` becomes the most powerful tool in the language.

## Sitemap

See the full [sitemap](https://learnrust.net/sitemap.md) for all pages.
