Traits can also be parameters. These functions are similar to generics, but restrict the types to types that implement the trait. Example:
pub trait Shape {
fn area(&self) -> f32;
}
pub trait TwoD {}
pub struct Circle {
radius: f32,
}
impl Shape for Circle {
fn area(&self) -> f32 {
self.radius * 3.14159
}
}
impl TwoD for Circle {}
// Traits as parameters - short hand
pub fn print_area(s: &impl Shape) {
println!("{}", s.area());
}
// Traits as parameters - the long way
pub fn print_area2<T: Shape>(s: &T) {
println!("{}", s.area());
}
// Multiple Traits
pub fn print_area3<T: Shape + TwoD>(s: &T) {
println!("{}", s.area());
}
// where can be used to make trait bounds look pretty
pub fn print_areas<T, U>(s: &T, r: &U)
where T: Shape + TwoD,
U: Shape
{
println!("{}", s.area());
println!("{}", r.area());
}
// Return type that implements trait
pub fn get_area(s: &str) -> impl Shape {
if s == "Circle" {
return Circle { radius: 0.0 };
}
Circle { radius: 0.0 } // Imagine other Shapes being here
}
fn main() {
let cir = Circle { radius: 12.25 };
print_area3(&cir);
print_areas(&cir, &cir);
}