1. Traits
trait Summary {
fn summarize_author(&self) -> String;
// Default implementation
fn summarize(&self) -> String {
format!("(Read more from {}...)", self.summarize_author())
}
}
struct Article {
title: String,
author: String,
content: String,
}
impl Summary for Article {
fn summarize_author(&self) -> String {
self.author.clone()
}
fn summarize(&self) -> String {
format!("{} by {}: {}...", self.title, self.author, &self.content[..50])
}
}
2. Generics & Trait Bounds
// Generic function
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in &list[1..] {
if item > largest {
largest = item;
}
}
largest
}
// Multiple trait bounds
fn print_summary<T: Summary + std::fmt::Display>(item: &T) {
println!("{}: {}", item, item.summarize());
}
// where clause — dễ đọc hơn
fn complex_function<T, U>(t: &T, u: &U) -> String
where
T: Summary + Clone,
U: std::fmt::Display + std::fmt::Debug,
{
format!("{} - {:?}", t.summarize(), u)
}
// Generic struct
struct Pair<T> {
first: T,
second: T,
}
impl<T: std::fmt::Display + PartialOrd> Pair<T> {
fn larger(&self) -> &T {
if self.first >= self.second { &self.first } else { &self.second }
}
}
3. Associated Types & Supertraits
// Associated type — type placeholder trong trait
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
struct Counter {
count: u32,
max: u32,
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count < self.max {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
// Supertrait — trait kế thừa
trait PrettyPrint: std::fmt::Display {
fn pretty_print(&self) {
println!("╔══════════════╗");
println!("║ {} ║", self);
println!("╚══════════════╝");
}
}
4. impl Trait vs dyn Trait
// impl Trait — static dispatch (monomorphization)
fn notify(item: &impl Summary) -> impl std::fmt::Display {
format!("Breaking: {}", item.summarize())
}
// dyn Trait — dynamic dispatch (trait object)
fn get_formatter(format: &str) -> Box<dyn Summary> {
match format {
"article" => Box::new(Article { /* ... */ }),
"tweet" => Box::new(Tweet { /* ... */ }),
_ => panic!("Unknown format"),
}
}
// Common derives
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct ProductId(String);
// From/Into
impl From<String> for ProductId {
fn from(s: String) -> Self {
ProductId(s)
}
}
let id: ProductId = "abc".to_string().into();
Next article: Closures, Iterators & Collections.