Traits
A trait
is a collection of methods defined for an unknown type: Self
. They can access other methods declared in the same trait.
Traits can be implemented for any data type. In the example below, we define Animal
, a group of methods. The Animal
trait
is then implemented for the Sheep
data type, allowing the use of methods from Animal
with a Sheep
:
struct Sheep { naked: bool, name: &'static str }trait Animal {// Associated function signature; `Self` refers to the implementor type.fn new(name: &'static str) -> Self;// Method signatures; these will return a string.fn name(&self) -> &'static str;fn noise(&self) -> &'static str;// Traits can provide default method definitions.fn talk(&self) {println!("{} says {}", self.name(), self.noise());}}impl Sheep {fn is_naked(&self) -> bool {self.naked}fn shear(&mut self) {if self.is_naked() {// Implementor methods can use the implementor's trait methods.println!("{} is already naked...", self.name());} else {println!("{} gets a haircut!", self.name);self.naked = true;}}}// Implement the `Animal` trait for `Sheep`.impl Animal for Sheep {// `Self` is the implementor type: `Sheep`.fn new(name: &'static str) -> Sheep {Sheep { name: name, naked: false }}fn name(&self) -> &'static str {self.name}fn noise(&self) -> &'static str {if self.is_naked() {"baaaaah?"} else {"baaaaah!"}}// Default trait methods can be overridden.fn talk(&self) {// For example, we can add some quiet contemplation.println!("{} pauses briefly... {}", self.name, self.noise());}}fn main() {// Type annotation is necessary in this case.let mut dolly: Sheep = Animal::new("Dolly");// TODO ^ Try removing the type annotations.dolly.talk();dolly.shear();dolly.talk();}