Traits & Generics
Welcome to Traits & Generics
Section titled “Welcome to Traits & Generics”Two of Rust’s most powerful features work together to let you write code that is both flexible and safe:
- Traits define shared behavior — a contract that any type can fulfill.
- Generics enable parametric code — one function or struct that works for many types.
Together, they let you write expressive abstractions without giving up compile-time guarantees or paying runtime costs.
Why Traits?
Section titled “Why Traits?”In many languages you share behavior through inheritance. Rust takes a different approach: you define a trait (a set of method signatures), and any type can implement it independently. This is similar to interfaces in Java or Go, but with richer capabilities like default method bodies.
trait Greet { fn hello(&self) -> String;}Any struct that implements Greet must provide a hello method. The trait is a contract; the struct fulfills that contract.
Why Generics?
Section titled “Why Generics?”Without generics you would need a separate largest_i32, largest_f64, and largest_char function — all with identical bodies but different types. Generics let you write this once using a type parameter (written inside angle brackets in code, like fn largest<T: PartialOrd>(a: T, b: T) -> T).
The T: PartialOrd part is a trait bound — it tells the compiler “this function works for any type T that supports comparison.” The compiler then generates a specialized copy for each concrete type you actually use (a process called monomorphization).
Module Roadmap
Section titled “Module Roadmap”| Lesson | What you will learn |
|---|---|
| Traits | Define shared behavior, default methods, calling trait methods |
| Generics | Generic functions, generic structs, trait bounds, where clauses |
| Trait Objects | dyn Trait, Box<dyn Trait>, static vs dynamic dispatch |
| Lifetimes | Lifetime annotations, dangling references, elision rules |
Try It Now
Section titled “Try It Now”The snippet below shows a generic function with a trait bound, a custom trait, and a struct that implements it — all the ideas you will study in depth across this module.
fn main() { let x: i32 = 42; println!("x = {}", x);
// Generic function: works for any PartialOrd type fn largest<T: PartialOrd>(a: T, b: T) -> T { if a > b { a } else { b } }
println!("largest(3, 7) = {}", largest(3, 7)); println!("largest(3.14, 2.71) = {}", largest(3.14, 2.71));
// Trait usage trait Greet { fn hello(&self) -> String; }
struct Person { name: String }
impl Greet for Person { fn hello(&self) -> String { format!("Hello, {}!", self.name) } }
let p = Person { name: String::from("Rust") }; println!("{}", p.hello());}Compiling…