Traits
Definition
trait is a collection of methods defined for an unknown type: Self
trait is about behavior of a type
- orphan rule: when impl a trait, either the trait or the type must be new in the current crate
//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
- With Associated Type, one cannot implement a trait on a type multiple times
trait T { type X; } Only one impl T for S possible
trait T<X> {} can have multiple impl T for S (one per X)
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
- Add a method to an existing type
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
- Comparison traits:
Eq, PartialEq, Ord, PartialOrd.
Clone, to create T from &T via a copy.
Copy, to give a type ‘copy semantics’ instead of ‘move semantics’.
Hash, to compute a hash from &T.
Default, to create an empty instance of a data type.
Debug, to format a value using the {:?} formatter.
#[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 {
...
}