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();
}