use std::fmt;
trait Printable: fmt::Debug + fmt::Display {
fn print(&self) { println!("{}", self); }
fn debug_print(&self) { println!("{:?}", self); }
fn print_labeled(&self, label: &str) {
println!("{}: {}", label, self);
}
}
#[derive(Debug)]
struct Temperature(f64);
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:.1}°C", self.0)
}
}
impl Printable for Temperature {} // All methods use defaults!
// Extending traits
trait Animal: fmt::Display {
fn name(&self) -> &str;
fn sound(&self) -> &str;
fn describe(&self) -> String {
format!("{} says '{}'", self.name(), self.sound())
}
fn num_legs(&self) -> u8 { 4 } // default
}
struct Dog { name: String }
impl fmt::Display for Dog {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Dog({})", self.name) }
}
impl Animal for Dog {
fn name(&self) -> &str { &self.name }
fn sound(&self) -> &str { "woof" }
// num_legs uses default: 4
}
struct Spider { name: String }
impl fmt::Display for Spider {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Spider({})", self.name) }
}
impl Animal for Spider {
fn name(&self) -> &str { &self.name }
fn sound(&self) -> &str { "..." }
fn num_legs(&self) -> u8 { 8 } // Override default
}
fn main() {
let t = Temperature(25.0);
t.print();
t.print_labeled("Temp");
let d = Dog { name: "Rex".to_string() };
let s = Spider { name: "Charlotte".to_string() };
println!("{} legs: {}", d.describe(), d.num_legs());
println!("{} legs: {}", s.describe(), s.num_legs());
}