Traits and derived behavior
Traits and derived behavior
Several kinds of school records might provide a label. A trait defines shared behavior that different types can implement, without requiring a common class hierarchy. Derive can generate supported standard trait implementations from a type’s fields.
What you’ll learn
- Implement shared behavior for a student type.
- Distinguish diagnostic derives and dynamic trait dispatch.
Traits and derived behavior in action
Student stores a name
The trait implementation creates a human-facing label.
Student stores a nameLabeled supplies behavior
The generated Debug implementation produces a structural diagnostic representation.
Labeled supplies behaviorDebug supplies diagnostic view
Both methods borrow the record, so calling one does not prevent the other.
Debug supplies diagnostic view
Traits and derived behavior explained
Define a trait’s method signature, then implement it for a struct. A method can borrow &self and return owned display text. #[derive(Debug)] generates a Debug implementation if the fields support it. Traits describe supported operations; they do not automatically share field storage between types.
Work through the Rust program
Save the complete source as main.rs in the Rust environment. No standard input is needed.
Rust 2024 · complete program
#[derive(Debug)]
struct Student { name: String }
trait Labeled { fn label(&self) -> String; }
impl Labeled for Student {
fn label(&self) -> String { format!("Student: {}", self.name) }
}
fn main() {
let student = Student { name: "Diya".to_string() };
println!("{}", student.label());
println!("{student:?}");
}Expected output
Student: Diya
Student { name: "Diya" }Follow the execution
The trait implementation creates a human-facing label. The generated Debug implementation produces a structural diagnostic representation. Both methods borrow the record, so calling one does not prevent the other.
Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.
One trait, two dispatch choices
A generic trait bound allows specialization for a concrete type. A borrowed &dyn Labeled is a trait object, carrying information that selects an implementation at runtime. It supports different compatible implementations behind one interface, with an indirect call and restrictions on which traits support dynamic dispatch.
Rust 2024 · complete program
struct Student { name: String }
trait Labeled { fn label(&self) -> String; }
impl Labeled for Student {
fn label(&self) -> String { format!("Student: {}", self.name) }
}
fn show(item: &dyn Labeled) { println!("{}", item.label()); }
fn main() {
let student = Student { name: "Diya".to_string() };
show(&student);
}Expected output
Student: DiyaShow borrows the student through its trait interface. Calling label selects the Student implementation, which formats the name. The helper does not own or duplicate the student record.
Try a small variation
Your task: Does implementing Labeled automatically create a name field in every type?
Rust 2024 · complete program
#[derive(Debug)]
struct Student { name: String }
trait Labeled { fn label(&self) -> String; }
impl Labeled for Student {
fn label(&self) -> String { format!("Student: {}", self.name) }
}
fn main() {
let student = Student { name: "Diya".to_string() };
println!("{}", student.label());
println!("{student:?}");
}Worked answer
No. Each implementing type supplies the promised behavior using its own representation. A trait is a behavior contract, not a shared storage layout.
Mistakes and limits to recognize
Derive only supports traits that provide a derive implementation and whose requirements are met. Manual implementations can enforce domain-specific behavior. Trait and implementation placement also follows coherence rules; not every external trait can be implemented for every external type.
Check your understanding
Take the idea into your next program
No. Each implementing type supplies the promised behavior using its own representation. A trait is a behavior contract, not a shared storage layout. Derive only supports traits that provide a derive implementation and whose requirements are met.
Further reading: the official Rust Book on traits and derived behavior.
Reaching the recap and completing the quizzes are separate milestones.