In Rust, a trait can be thought of as the equivalent of a Java interface (used to achieve abstraction). A struct can implement a trait using the impl
keyword and specify its own definition of the trait’s methods. For example, Herbivore
and Carnivore
structs can implement the Animal
trait and give their specific implementations of the eat
method:
#![allow(dead_code)]fn main(){trait Animal {fn eat(&self);}struct Herbivore;struct Carnivore;impl Animal for Herbivore {fn eat(&self) {println!("I eat plants");}}impl Animal for Carnivore {fn eat(&self) {println!("I eat flesh");}}let h = Herbivore;h.eat();}
A trait object is an object that can contain objects of different types at the same time (e.g., a vector). The dyn
keyword is used when declaring a trait object:
The size of a trait is not known at compile-time; therefore, traits have to be wrapped inside a
Box
when creating a vector trait object.
fn main() {trait Animal {fn eat(&self);}struct Herbivore;struct Carnivore;impl Animal for Herbivore {fn eat(&self) {println!("I eat plants");}}impl Animal for Carnivore {fn eat(&self) {println!("I eat flesh");}}// Create a vector of Animals:let mut list: Vec<Box<dyn Animal>> = Vec::new();let goat = Herbivore;let dog = Carnivore;list.push(Box::new(goat));list.push(Box::new(dog));// Calling eat() for all animals in the list:for animal in &list{animal.eat();}}