You can define a trait using the trait
keyword, followed by the name of the trait and a set of method signatures, without any implementation. For example:
trait Shape { fn area(&self) -> f64; fn perimeter(&self) -> f64; }
This defines a trait called Shape
with two methods, area
and perimeter
, both of which take a reference to self and return a value of type f64
.
A struct or an enum can implement a trait by using the impl
keyword and providing the method implementation. For example:
struct Square { side: f64, } impl Shape for Square { fn area(&self) -> f64 { self.side * self.side } fn perimeter(&self) -> f64 { self.side * 4.0 } }
This implements the Shape
trait for the Square
struct, providing specific implementation for area
and perimeter
methods.
You can use trait bounds to specify that a generic type must implement a particular trait. For example:
fn print_area<T: Shape>(shape: T) { println!("Area is: {}", shape.area()); }
This defines a function print_area
that takes a value of any type T
that implements the Shape
trait. This way the function will have access to the area
method of the shape.
Traits can also be used to define static dispatch or dynamic dispatch in Rust. Static dispatch uses the type of the value at compile time to determine the implementation of the trait, while dynamic dispatch uses the runtime type of the value to determine the implementation of the trait.
Social Plugin