Rust Traits
A trait defines a set of behavior that a type can implement — a bit like an interface in other languages. It’s how Rust describes “this type can do X,” and it’s what powers the trait bounds you saw on the Generics page.
Defining a trait
Section titled “Defining a trait”trait Speak { fn speak(&self) -> String;}This says: any type that implements Speak must provide a speak method that returns a String. On its own, a trait is just a promise — it doesn’t do anything until some type implements it.
Implementing a trait
Section titled “Implementing a trait”trait Speak { fn speak(&self) -> String;}
struct Dog;struct Cat;
impl Speak for Dog { fn speak(&self) -> String { String::from("Woof!") }}
impl Speak for Cat { fn speak(&self) -> String { String::from("Meow!") }}
fn main() { let dog = Dog; let cat = Cat;
println!("{}", dog.speak()); println!("{}", cat.speak());}Output:
Woof!Meow!Dog and Cat are unrelated types, but both implement Speak, so both can be called with .speak(). This is the same pattern as impl blocks on the Structs page — impl Speak for Dog just says “here’s how Dog fulfills the Speak trait.”
Traits as function parameters
Section titled “Traits as function parameters”The real payoff: you can write a function that accepts any type implementing a trait, without caring which specific type it is:
trait Speak { fn speak(&self) -> String;}
struct Dog;impl Speak for Dog { fn speak(&self) -> String { String::from("Woof!") }}
fn announce(animal: &impl Speak) { println!("The animal says: {}", animal.speak());}
fn main() { let dog = Dog; announce(&dog);}animal: &impl Speak means “any type that implements Speak, I don’t need to know which one.” Add a Bird type that also implements Speak, and announce works with it too, with no changes.
Traits you’ve already used
Section titled “Traits you’ve already used”Remember #[derive(Debug)] from the Structs page? Debug is itself a trait — derive just auto-generates the implementation for you instead of you writing it by hand. Other common ones you’ll run into: Clone (for .clone()), PartialEq (for ==), and PartialOrd (for <, >, which you saw used as a trait bound on the Generics page).
Default implementations
Section titled “Default implementations”A trait can provide a default method body, which implementing types can use as-is or override:
trait Greet { fn name(&self) -> String;
fn greet(&self) -> String { format!("Hello, {}!", self.name()) }}Any type implementing Greet only has to define name() — greet() comes for free, unless it chooses to override it too.
There’s more to traits than this page covers. The Common Traits page walks through the standard ones you’ll use every day, and Advanced Traits covers associated types, supertraits and other tools you’ll see in bigger codebases.
Practice
Section titled “Practice”1. Shapes with an area
Section titled “1. Shapes with an area”Define a trait Area with one method, fn area(&self) -> f64. Implement it for a Rectangle (with width and height) and a Square (with side). Print the area of a 3 by 4 rectangle and a square with side 5. Hint: each impl Area for ... block only needs the one method, and its body is a single multiplication.
Show solution
trait Area { fn area(&self) -> f64;}
struct Rectangle { width: f64, height: f64,}
struct Square { side: f64,}
impl Area for Rectangle { fn area(&self) -> f64 { self.width * self.height }}
impl Area for Square { fn area(&self) -> f64 { self.side * self.side }}
fn main() { let rect = Rectangle { width: 3.0, height: 4.0 }; let square = Square { side: 5.0 };
println!("Rectangle: {}", rect.area()); println!("Square: {}", square.area());}Output:
Rectangle: 12Square: 252. One function for many types
Section titled “2. One function for many types”Define a trait Describe with fn describe(&self) -> String. Implement it for a Book (with a title) and a Movie (with a title and minutes). Then write one function fn show(item: &impl Describe) that prints the description, and call it with both. Hint: use format! to build each description string.
Show solution
trait Describe { fn describe(&self) -> String;}
struct Book { title: String,}
struct Movie { title: String, minutes: u32,}
impl Describe for Book { fn describe(&self) -> String { format!("Book: {}", self.title) }}
impl Describe for Movie { fn describe(&self) -> String { format!("Movie: {} ({} min)", self.title, self.minutes) }}
fn show(item: &impl Describe) { println!("{}", item.describe());}
fn main() { let book = Book { title: String::from("The Hobbit") }; let movie = Movie { title: String::from("Up"), minutes: 96 };
show(&book); show(&movie);}Output:
Book: The HobbitMovie: Up (96 min)3. Use or override a default
Section titled “3. Use or override a default”Take the Greet trait from this page, with its default greet() method. Implement it for a Person, which keeps the default, and for a Pirate, which overrides greet() to say Ahoy, ...! instead. Hint: both types must define name(). Only Pirate also writes its own greet().
Show solution
trait Greet { fn name(&self) -> String;
fn greet(&self) -> String { format!("Hello, {}!", self.name()) }}
struct Person { name: String,}
struct Pirate { name: String,}
impl Greet for Person { fn name(&self) -> String { self.name.clone() }}
impl Greet for Pirate { fn name(&self) -> String { self.name.clone() }
fn greet(&self) -> String { format!("Ahoy, {}!", self.name()) }}
fn main() { let ana = Person { name: String::from("Ana") }; let jack = Pirate { name: String::from("Jack") };
println!("{}", ana.greet()); println!("{}", jack.greet());}Output:
Hello, Ana!Ahoy, Jack!- A trait defines behavior a type can implement, similar to an interface.
impl TraitName for Typeprovides the implementation.&impl TraitNameas a parameter type accepts any type implementing that trait.- Traits can supply default method bodies that implementers can use or override.
Debug,Clone, andPartialEqare common traits from the standard library —#[derive(...)]implements them automatically.
Quick check
Section titled “Quick check”Quick check
1. What does a trait define?
2. What does animal: &impl Speak as a parameter type mean?
3. What is #[derive(Debug)] actually doing?
4. What is a default implementation in a trait?
5. Which of these is a trait, not a struct or enum, according to this page?
Score: 0 / 5
Read more
Section titled “Read more”- Traits: Defining Shared Behavior — The Rust Book: the official chapter on defining traits, default methods,
impl Traitparameters and trait bounds. - Traits — Rust by Example: a runnable example with a trait, a default method and an implementation.
- Derive — Rust by Example: which standard traits
#[derive(...)]can implement for you, with examples. - Advanced Traits — The Rust Book: the next step, with associated types, supertraits and the newtype pattern.
- Traits — The Rust Reference: the precise rules for trait definitions, for when you want the full details.