Generics let you write flexible code that works with many types. Traits tell Rust what actions a type can do. Together, they help make reusable and safe code.
0
0
Generics with traits in Rust
Introduction
When you want a function to work with different types but need certain abilities from those types.
When creating a struct that can hold any type that supports specific actions.
When you want to write code that is general but still checks that types behave as expected.
When you want to avoid repeating similar code for different types.
When you want to enforce rules on types used in your code.
Syntax
Rust
fn function_name<T: TraitName>(param: T) {
// code using param with TraitName methods
}
struct StructName<T: TraitName> {
field: T,
}
impl<T: TraitName> StructName<T> {
fn method(&self) {
// use trait methods on self.field
}
}T: TraitName means type T must implement TraitName.
You can use multiple traits with T: Trait1 + Trait2.
Examples
This function accepts any type T that implements the
Shape trait, so it can call area().Rust
fn print_area<T: Shape>(shape: T) {
println!("Area: {}", shape.area());
}This struct holds any type that can be displayed as text, enforced by the
Display trait.Rust
struct Container<T: std::fmt::Display> {
item: T,
}
impl<T: std::fmt::Display> Container<T> {
fn show(&self) {
println!("Item: {}", self.item);
}
}This function compares two values of any type that can be ordered.
Rust
fn compare<T: PartialOrd>(a: T, b: T) -> bool {
a > b
}Sample Program
This program defines a trait Summary and a struct NewsArticle that implements it. The generic function notify accepts any type that implements Summary and prints a message.
Rust
use std::fmt::Display; // Define a trait with a method trait Summary { fn summarize(&self) -> String; } // Implement trait for a struct struct NewsArticle { headline: String, location: String, } impl Summary for NewsArticle { fn summarize(&self) -> String { format!("{} - {}", self.headline, self.location) } } // Generic function requiring Summary trait fn notify<T: Summary>(item: T) { println!("Breaking news: {}", item.summarize()); } fn main() { let article = NewsArticle { headline: String::from("Rust is awesome!"), location: String::from("Internet"), }; notify(article); }
OutputSuccess
Important Notes
Traits define what methods a type must have to be used with generics.
Using traits with generics helps catch errors early because Rust checks if types implement required traits.
You can use trait bounds on structs, functions, and implementations.
Summary
Generics let you write flexible code that works with many types.
Traits specify what actions types must support.
Combining generics with traits ensures your code works only with types that have needed abilities.