Advanced

Traits and Generics

Write reusable code with Rust traits (like interfaces) and generic types.

Traits

Traits define shared behavior. They're similar to interfaces in other languages but more powerful.

You can implement traits for any type, even types you didn't define.

Generics

Write functions and types that work with multiple types while preserving type safety.

Trait Bounds

Constrain generic types to those that implement specific traits.

Common Standard Traits

  • Display: How to format for printing ({})
  • Debug: How to format for debugging ({:?})
  • Clone: Deep copy
  • Copy: Stack copy (implicit)
  • Iterator: Custom iterators

Example

rust
use std::fmt;

// Define a trait
trait Summary {
    fn summarize(&self) -> String;
    fn author(&self) -> String;

    // Default implementation
    fn preview(&self) -> String {
        format!("{}... - {}", &self.summarize()[..50.min(self.summarize().len())], self.author())
    }
}

struct Article {
    title: String,
    content: String,
    author: String,
}

struct Tweet {
    username: String,
    content: String,
}

impl Summary for Article {
    fn summarize(&self) -> String { self.content.clone() }
    fn author(&self) -> String { self.author.clone() }
}

impl Summary for Tweet {
    fn summarize(&self) -> String { self.content.clone() }
    fn author(&self) -> String { format!("@{}", self.username) }
}

// Generic function with trait bound
fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.preview());
}

// Generic with where clause
fn compare_summaries<T, U>(t: &T, u: &U) -> String
where
    T: Summary + fmt::Debug,
    U: Summary,
{
    format!("{} vs {}", t.summarize(), u.summarize())
}

// Generic struct
struct Pair<T> {
    first: T,
    second: T,
}

impl<T: PartialOrd + fmt::Display> Pair<T> {
    fn largest(&self) -> &T {
        if self.first >= self.second { &self.first } else { &self.second }
    }
}

fn main() {
    let article = Article {
        title: String::from("Rust is Amazing"),
        content: String::from("Rust provides memory safety without GC."),
        author: String::from("Alice"),
    };

    let tweet = Tweet {
        username: String::from("rustlang"),
        content: String::from("Exciting news about Rust 2024!"),
    };

    notify(&article);
    notify(&tweet);

    let pair = Pair { first: 5, second: 10 };
    println!("Largest: {}", pair.largest());  // 10
}
Try it yourself — RUST