🎭
World 18 Β· Object-Oriented Rust

Many Shapes, One Box

Imagine a list of different animals β€” a dog, a cat, a duck. They are all different, but they can all make a sound. 🐾 Today we’ll learn how Rust lets us keep different types together in one list and ask each of them to do the same thing.

The Big Idea A trait is a shared promise β€” like "I can make a sound." A trait object lets us put different types that all keep that same promise into one list, then ask each one to keep its promise.

A trait is a shared promise

Way back in World 10 we met traits. A trait is a list of things a type promises it can do. Here we make a trait called Speak β€” anything that has Speak promises it can make a sound.

trait Speak {
    fn speak(&self) -> String;
}

A Dog and a Cat are totally different types. But if they both promise Speak, we can treat them the same way when we just want them to talk. πŸ—£οΈ

Putting them in one box

Normally a Vec (a list) can only hold one type. So how do we mix dogs and cats? We wrap each one in a Box<dyn Speak>. The word dyn means β€œany type that keeps the Speak promise.” Now the list doesn’t care what animal it is β€” only that it can speak!

New word Box<dyn Speak> means "a box holding some type that promises Speak β€” we don't need to know exactly which one."
</div> See that? One loop, two very different animals, each making its own sound. We never had to ask "are you a dog or a cat?" β€” we just said "speak!" and each knew what to do. πŸŽ‰
Think of it like this… A trait object is like a choir. Every singer is different, but the conductor waves their hands and says "sing!" β€” and each one sings in their own voice. 🎢
## Add a new animal anytime Want a duck too? Just give it the `Speak` promise and drop it in the box. The loop doesn't change at all!
</div>
Ferris says: The magic word is dyn. It tells Rust, "figure out which animal it is when the program runs, then call the right sound." πŸ¦€
Try this! Go back to the first code box. Add a new struct Cow; with a speak that returns "Moo!", then add Box::new(Cow) to the vec!. Press β–Ά Run and watch the cow join in!
## Quick quiz

Why do we wrap our animals in Box<dyn Speak>?

Yes! Box<dyn Speak> lets us mix different types in one list, as long as they all keep the Speak promise.

You learned… A trait object like Box<dyn Speak> lets you keep different types together in one list and call their shared method β€” no matter what each one really is. Next up: we'll learn how Rust remembers things step by step in State Patterns! 🚦