Trait = a contract (behavior).
It says: “Any type that implements this trait must provide these methods.”
Why we use traits
Write reusable code: one function works for many types.
Polymorphism (like interfaces): treat different types the same way if they share behavior.
Operator overloading: +, ==, println! etc. work via traits (Add, PartialEq, Display).
Extending types: add methods to existing types using an “extension trait”.
Cleaner architecture: separate behavior from data types.
When we use traits
When you want a function to accept multiple different types that behave similarly.
When you want compile-time safety + speed (static dispatch via generics).
When you want *runtime polymorphism *(dynamic dispatch via dyn Trait) for plugin-like systems.
When you need standard behavior (printing, cloning, comparing, iterating).
Basic trait + implementation
trait Speak {
fn speak(&self) -> &'static str;
}
struct Dog;
struct Cat;
impl Speak for Dog {
fn speak(&self) -> &'static str { "Woof" }
}
impl Speak for Cat {
fn speak(&self) -> &'static str { "Meow" }
}
fn main() {
let d = Dog;
let c = Cat;
println!("{}", d.speak());
println!("{}", c.speak());
}
Output
Woof
Meow
2) Trait as function parameter (generic bound)
trait Area {
fn area(&self) -> i32;
}
struct Square(i32);
struct Rect(i32, i32);
impl Area for Square {
fn area(&self) -> i32 { self.0 * self.0 }
}
impl Area for Rect {
fn area(&self) -> i32 { self.0 * self.1 }
}
fn print_area<T: Area>(shape: &T) {
println!("Area = {}", shape.area());
}
fn main() {
print_area(&Square(5));
print_area(&Rect(4, 6));
}
Output
Area = 25
Area = 24
3) Default method in a trait
trait Greet {
fn name(&self) -> &str;
fn greet(&self) {
println!("Hello, {}", self.name());
}
}
struct User { name: String }
impl Greet for User {
fn name(&self) -> &str { &self.name }
}
fn main() {
let u = User { name: "Ashwani".to_string() };
u.greet();
}
Output
Hello, Ashwani
4) Trait + impl Trait return type
trait Label {
fn label(&self) -> String;
}
struct Product { id: i32 }
impl Label for Product {
fn label(&self) -> String { format!("Product#{}", self.id) }
}
fn make_labeler(id: i32) -> impl Label {
Product { id }
}
fn main() {
let x = make_labeler(101);
println!("{}", x.label());
}
Output
Product#101
5) Trait objects (dyn Trait) for runtime polymorphism
trait Pay {
fn pay(&self) -> i32;
}
struct Cash(i32);
struct Card(i32);
impl Pay for Cash { fn pay(&self) -> i32 { self.0 } }
impl Pay for Card { fn pay(&self) -> i32 { self.0 } }
fn total_payments(items: Vec<Box<dyn Pay>>) -> i32 {
items.into_iter().map(|x| x.pay()).sum()
}
fn main() {
let items: Vec<Box<dyn Pay>> = vec![Box::new(Cash(200)), Box::new(Card(500))];
println!("Total = {}", total_payments(items));
}
Output
Total = 700
6) Associated types in traits
trait Convert {
type Output;
fn convert(&self) -> Self::Output;
}
struct Meter(i32);
impl Convert for Meter {
type Output = i32; // centimeters
fn convert(&self) -> i32 { self.0 * 100 }
}
fn main() {
let m = Meter(3);
println!("{}", m.convert());
}
Output
300
7) Trait bounds with multiple traits (Display + Clone)
use std::fmt::Display;
fn print_twice<T: Display + Clone>(x: T) {
println!("{}", x.clone());
println!("{}", x);
}
fn main() {
print_twice(String::from("Rust"));
}
Output
Rust
Rust
8) Implementing standard library trait Display (custom printing)
use std::fmt;
struct Point { x: i32, y: i32 }
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: 5, y: 7 };
println!("Point = {}", p);
}
Output
Point = (5, 7)
9) Extension trait (add new method to existing type)
trait MyStrExt {
fn shout(&self) -> String;
}
impl MyStrExt for str {
fn shout(&self) -> String {
format!("{}!!!", self.to_uppercase())
}
}
fn main() {
let s = "hello";
println!("{}", s.shout());
}
Output
HELLO!!!
10) Generic algorithm using trait PartialOrd (works for many types)
fn max_of<T: PartialOrd>(a: T, b: T) -> T {
if a > b { a } else { b }
}
fn main() {
println!("{}", max_of(10, 20));
println!("{}", max_of(5.5, 3.2));
}
Output
20
5.5
Top comments (0)