Basics

Rust Atomics and Locks Series


OOP

pub struct Foo {/* */}

impl Foo {
    //blah
}

impl Something for FOo {
    //blah
}

Traits

  • Comparison: Eq, PartialEq, Ord, partialOrd,
  • Clone: T from &T
  • Copy: replace move to copy semantics
  • Hash: compute hash from &T
  • Default: empty instance of a data type
  • Debug: {:?} formatter
  • Send: safe toe send it to another thread
  • Sync: safe to share between thread (T is Sync if &T is Send)

Returning trait objects (dyn)

struct Sheep {}
struct Cow {}

trait Animal {
    fn noise(&self) -> &'static str;
}

impl Animal for Sheep;
impl Animal for Cow;

fn random_animal(num: f64) -> Box<dyn Animal> {
    Box::new(Sheep {})
    //or
    Box::new(Cow {})
}

Static dispatch

fn show_item<T: fmt::Display>(item: T) {
    println!("{}", item);
}

// items that implements fmt::Display
impl fmt::Display for CanDisplay {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CanDisplay");
    }
}

Dynamic dispatch

use std::fmt;

// A custom type for which we will implement the `fmt::Display` trait.
struct CanDisplay;

impl fmt::Display for CanDisplay {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CanDisplay")
    }
}

// A different custom type that also implements the `fmt::Display` trait.
struct AnotherCanDisplay;

impl fmt::Display for AnotherCanDisplay {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AnotherCanDisplay")
    }
}

// A function that takes a trait object.
// The `dyn` keyword is used to indicate dynamic dispatch.
// This function can accept any type that implements `fmt::Display`.
fn show_item_dynamic(item: &dyn fmt::Display) {
    println!("{}", item);
}

fn main() {
    let my_struct = CanDisplay;
    let my_other_struct = AnotherCanDisplay;
    let my_string = String::from("Hello from a String");

    // All these types can be passed to the same function because they
    // all satisfy the `&dyn fmt::Display` trait object.
    show_item_dynamic(&my_struct);
    show_item_dynamic(&my_other_struct);
    show_item_dynamic(&my_string);

    // Dynamic dispatch is particularly useful for heterogeneous collections.
    // This isn't possible with static dispatch.
    let items: Vec<&dyn fmt::Display> = vec![
        &my_struct,
        &my_other_struct,
        &my_string,
        &42, // An `i32` also implements `fmt::Display`
    ];

    for item in items {
        show_item_dynamic(item);
    }
}