Rust :: Traits

Traits

Definition

//definition
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

// impl method
impl TraitSmaple for SomeType {
    fn some_fn { /* impl here */ }
    // use default impl for other_fn without def
}

// impl as Parameters
// some_fn will take any type that impl TraitSample
pub fn some_fn(item: &impl TraitSample) {
    item.some_fn(); 
}

// note that trait bounds after fn but not in signature
pub fn some_fn<T: TraitSample>(item1: &T, item2: &T) {}
pub fn some_fn(item: &(impl Display + SomeTrait)) {}
pub fn some_fn<T: Display + SomeTrait>(item: &T) {}

impl<T: Display> SomeStruct<T> { ... }

fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {}
// use where instead
fn some_function<T, U>(t: &T, u: &U) -> i32
    where T: Display + Clone,
          U: Clone + Debug
{}

// returning Types that impl Traits
fn some_fn() -> impl SomeTrait {}
// if the size is unknown, use Box<>
fn some_fn() -> Box<dyn SomeTrait> { ... }

// overlapping traits
// When a type impl two Traits with methods of the same name
<SomeStruct as FirstTrait>::fn()
<SomeStruct as Second Trait>::fn()

Associated Types

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    ...
}

Associated Consts

trait Greet {
    const GREETING: &'static str = "Hello";
    fn greet(&self) -> String;
}

// can declare without a value
trait Float {
    const ZERO: Self;
    const ONE: Self;
}
impl Float for f64 {
    const ZERO: f64 = 0.0;
    const ONE: f64 = 1.0;
}
fn add_one<T: Float + Add<Output=T>>(value: T) -> T {
    value + T::ONE
}

Method Calls

"hello".to_string()             // qualified method calls
str::to_string("hello")         // call on `str` type impl
ToString::to_string("hello")    // call on Trait "ToString" assocaited fn
<str as ToString>::to_string("hello")   // full qualified method calls

// use full qualified method calls
// when two methods have the same name
Trait1::fn(&value);
Trait2::fn(&value);

// when the type of `self` cant be inferred
let zero = 0;
zero.abs();     // error
i64::abs(zero); // pass

// when using the function itself as a function value
let words: Vec<String> =
    line.split_whitespace()  // iterator produces &str values
        .map(ToString::to_string)  // ok
        .collect();

Extension trait

trait WriteHtml {
    fn write_html(&mut self, html: &HtmlDoc) -> io::Result<()>;
}

// impl this trait to all Writers
// adding a method to all Rust writers
impl<W: Write> WriteHtml for W {
    fn write_html(&mut self, html: &HtmlDoc) -> io::Result<()> {
        ...
    }
}

Derivable Traits

#[derive(PartialEq,PartialOrd)]

Supertrait

// Rust's "inheritance"
trait Person {
    fn name(&self) -> String;
}

// Person is a supertrait of Student.
// Implementing Student requires you to also impl Person.
trait Student: Person {
    fn university(&self) -> String;
}
// just a shorthand for a bound on `Self`
trait Student where Self: Person {
    ...
}