通过例子学习Rust

30 接口(Traits)

A trait is a collection of methods declared/defined for an unknown type: Self. Traits can be implemented for any data type.

trait Animal { // Static method signature; `Self` refers to the implementor type fn new(name: &'static str) -> Self; // Instance methods, only signatures fn name(&self) -> &'static str; fn noise(&self) -> &'static str; // A trait can provide default method definitions fn talk(&self) { // These definitions can access other methods declared in the same // trait println!("{} says {}", self.name(), self.noise()); } } struct Dog { name: &'static str } impl Dog { fn wag_tail(&self) { println!("{} wags tail", self.name); } } // Implement the `Animal` trait for `Dog` impl Animal for Dog { // Replace `Self` with the implementor type: `Dog` fn new(name: &'static str) -> Dog { Dog { name: name } } fn name(&self) -> &'static str { self.name } fn noise(&self) -> &'static str { "woof!" } // Default trait methods can be overridden fn talk(&self) { // Traits methods can access the implementor methods self.wag_tail(); println!("{} says {}", self.name, self.noise()); } } struct Sheep { naked: bool, name: &'static str } 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.talk(); self.naked = true; } } } impl Animal for 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() { "baaah" } else { "baaaaaaaaaaaah" } } } fn main() { // Type annotation is necessary in this case let mut dolly: Sheep = Animal::new("Dolly"); let spike: Dog = Animal::new("Spike"); // TODO ^ Try removing the type annotations dolly.shear(); spike.talk(); dolly.talk(); }