← Rust EnglishChapter 10 of 13

Traits

## Learning Objectives - Define and implement traits - Use trait bounds - Default implementations - Master common standard traits - Work with generictraits ## What are Traits? Traits define shared behavior across types: ```rust trait Summary { fn summarize(&self) -> String; } ``` ## Implementing Traits ### Basic Implementation ```rust trait Summary { fn summarize(&self) -> String; } struct Article { title: String, author: String, } impl Summary for Article { fn summarize(&self) -> String { format!("{} by {}", self.title, self.author) } } fn main() { let article = Article { title: String::from("Rust Tutorial"), author: String::from("Alice"), }; println!("{}", article.summarize()); } ``` ### Multiple Traits ```rust trait Summarize { fn summarize(&self) -> String; } trait Printable { fn print(&self); } struct Article { title: String, author: String, } impl Summarize for Article { fn summarize(&self) -> String { format!("{} by {}", self.title, self.author) } } impl Printable for Article { fn print(&self) { println!("Title: {}\nAuthor: {}", self.title, self.author); } } ``` ## Default Implementations ```rust trait Summary { fn summarize(&self) -> String { String::from("(Read more...)") // Default implementation } } struct Tweet { username: String, content: String, } impl Summary for Tweet { // Uses default summarize implementation // Or override: // fn summarize(&self) -> String { // format!("@{}: {}", self.username, self.content) // } } fn main() { let tweet = Tweet { username: String::from("alice"), content: String::from("Hello world"), }; println!("{}", tweet.summarize()); // (Read more...) } ``` ## Trait Bounds ### Basic Syntax ```rust fn notify(item: &impl Summary) { println!("Breaking news! {}", item.summarize()); } ``` ### Trait Bound Syntax ```rust fn notify(item: &T) { println!("Breaking news! {}", item.summarize()); } ``` ### Multiple Trait Bounds ```rust fn notify(item: &(impl Summary + Display)) { } fn notify(item: &T) { } ``` ### where Clauses ```rust fn some_function(t: &T, u: &U) where T: Display + Clone, U: Clone + Debug, { // ... } ``` ## Conditionally Implement Methods ```rust use std::fmt::Display; struct Pair { x: T, y: T, } impl Pair { fn new(x: T, y: T) -> Self { Self { x, y } } } impl Pair { fn cmp_display(&self) { if self.x >= self.y { println!("The largest member is x = {}", self.x); } else { println!("The largest member is y = {}", self.y); } } } ``` ## Returning Types that Implement Traits ```rust trait Summary { fn summarize(&self) -> String; } fn returns_summarizable() -> impl Summary { Tweet { username: String::from("alice"), content: String::from("Hello"), } } ``` ## Using Trait Bounds for Conditional Methods ```rust use std::fmt::Display; struct Wrapper { value: T, } impl Wrapper { fn new(value: T) -> Self { Wrapper { value } } } impl Wrapper { fn print(&self) { println!("{}", self.value); } } impl Wrapper { fn eq(&self, other: &Wrapper) -> bool { self.value == other.value } } ``` ## Common Standard Traits ### Debug ```rust #[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect = Rectangle { width: 30, height: 50 }; println!("{:?}", rect); println!("{:#?}", rect); } ``` ### Clone and Copy ```rust #[derive(Clone, Copy)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // Copy let p3 = p1.clone(); // Clone println!("{:?}", p1); // p1 still valid (Copy) } ``` ### PartialEq and Eq ```rust #[derive(PartialEq, Eq)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = Point { x: 1, y: 2 }; println!("{}", p1 == p2); // true } ``` ### PartialOrd and Ord ```rust #[derive(PartialOrd, Ord)] struct Person { name: String, age: u32, } fn main() { let p1 = Person { name: "Alice".to_string(), age: 30 }; let p2 = Person { name: "Bob".to_string(), age: 25 }; println!("{}", p1 > p2); // true } ``` ### Display ```rust 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: 1, y: 2 }; println!("{}", p); // (1, 2) } ``` ### Default ```rust #[derive(Default)] struct Config { width: u32, height: u32, name: String, } fn main() { let config = Config { width: 100, ..Default::default() }; } ``` ## Blanket Implementations Implement trait for all types that satisfy bounds: ```rust use std::fmt::Display; impl T { fn print_twice(&self) { println!("{}", self); println!("{}", self); } } fn main() { 42.print_twice(); } ``` ## Supertraits Require a trait to implement another trait: ```rust use std::fmt::{Display, Debug}; trait OutlinePrint: Display { fn outline_print(&self) { let output = self.to_string(); let len = output.len(); println!("{}", "*".repeat(len + 4)); println!("* {} *", " ".repeat(len)); println!("* {} *", output); println!("* {} *", " ".repeat(len)); println!("{}", "*".repeat(len + 4)); } } struct Point { x: i32, y: i32, } impl Display for Point { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) } } impl OutlinePrint for Point {} ``` ## Summary - Traits define shared behavior (like interfaces) - Implement traits with `impl TraitName for Type` - Default implementations can be overridden - Trait bounds: `impl Trait` or `T: Trait` - Multiple bounds: `T: Trait1 + Trait2` - where clauses for complex bounds - `impl Trait` for return types - Common derive traits: Debug, Clone, Copy, PartialEq, Eq, Default - Blanket implementations: `impl Trait for T`

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →