Rust Traits

2021-08-25

~All ~Categories
pub trait Summary {
    fn summarize(&self) -> String;
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{} by {} ({})", self.headline, self.author, self.location)
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

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

fn main() {
    let tweet = Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };

    println!("1 new tweet: {}", tweet.summarize());
}

Traits as parameter🔗

pub fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}
pub fn notify_2<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}
// Convenient
// The following could receive two different type implementing Summary
pub fn notify_3a(item1: &impl Summary, item2: &impl Summary) {}
// If we wanted to force both param to have the same type
pub fn notify_3b<T: Summary>(item1: &T, item2: &T) {}
// Specifying multiple trait bound with the +Syntax
pub fn notify_4a(item: &(impl Summary + Display)) {}
pub fn notify_4b<T: Summary + Display>(item: &T) {}
// Clearer Trait bound with where clause
fn somefunction_a<T: Display + Clone, U: Clone + Display>(t: &T, u: &U) -> i32 {
    10
}

// Could be change for:
//---------------------
fn somefunction_b<T, U>(t: &T, u: &U) -> i32
where
    T: Display + Clone,
    U: Clone + Display,
{
    10
}
// Returning type that implement traits
fn return_summarizable() -> impl Summary {
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    }
}
// using trait bound to conditionnaly implement methods
use std::fmt::Display;

struct Pair<T> {
    x: T,
    y: T,
}

impl<T> Pair<T> {
    fn new(x: T, y: T) -> Self {
        Self { x, y }
    }
}

impl<T: Display + PartialOrd> Pair<T> {
    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);
        }
    }
}
// We can implement a trait for any type that implements another trait.
// blanket implementations
impl<T: Display> ToString for T {
  // --snip--
}

let s = 3.to_string();