Trait
Demo: trait-demo
It's similar to Interface in other languages. It describes an ability by containing a collection of methods.
For example, we've the struct
data types.
struct Satelite {
name: String,
velocity: f64,
}
struct SpaceStation {
name: String,
crew_size: u32,
}
We can create a trait
to print out their information.
trait Describable {
fn describe(&self) -> String;
}
Finally, we implement it for each struct
.
impl Describable for Satelite {
fn describe(&self) -> String {
format!("{} is travelling at {} km/s", self.name, self.velocity)
}
}
impl Describable for SpaceStation {
fn describe(&self) -> String {
format!("{} has a crew of {}", self.name, self.crew_size)
}
}
Default trait implementation
As we can see, the method in trait
was not implemented. Actually, We can implement it.
trait Describable {
fn describe(&self) -> String {
"Hello".to_string()
}
}
Then, the impl Describable for Satelite
and impl Describable for SpaceStation
can choose to override it or not.
Derive trait
Derive trait provides default implementations for severval common traits, which are:
Eq
PartialEq
Ord
PartialOrd
Clone
Copy
Hash
Default
Debug
For example, we want to compare between 2 satelites using ==
and >
.
#[derive(PartialEq, PartialOrd)]
struct Satelite {
name: String,
velocity: f64,
}
-
PartialEq
decides==
only if all the fields are equal. -
PartialOrd
decides>
just using the first field.
Trait bound
A trait bound sets the limits on the generic type.
For example, we need a generic type can be displayed, we add Display
trait bound to it, <T: fmt::Display>
.
use std::fmt;
fn print<T: fmt::Display>(item: T) {
println!("{}", item);
}
Multiple trait bounds
Sometimes, we need to use more than one trait bound.
use std::fmt;
fn compare<T: PartialEq + PartialOrd + fmt::Display>(item: T) {
// TODO
}
To make it more readable,
use std::fmt;
fn compare<T>(a: T, b: T)
where
T: PartialEq + PartialOrd + fmt::Display,
{
// TODO
}
Return Type with impl
Similar to trait bound, we can limit the output of a function.
fn get_displayable() -> impl fmt::Display {
"hi"
}