From d2535d80a8cc13bf54c23002387f0a4666006885 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 7 Feb 2019 13:31:29 -0500 Subject: [PATCH] Add advanced_traits example --- .idea/misc.xml | 1 + .idea/rust.iml | 5 ++ .idea/workspace.xml | 112 +++++++++++++++----------- advanced_traits/Cargo.toml | 7 ++ advanced_traits/src/main.rs | 151 ++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+), 46 deletions(-) create mode 100644 advanced_traits/Cargo.toml create mode 100644 advanced_traits/src/main.rs diff --git a/.idea/misc.xml b/.idea/misc.xml index fead741..66727c9 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -38,6 +38,7 @@ + diff --git a/.idea/rust.iml b/.idea/rust.iml index 32f1836..0831f61 100644 --- a/.idea/rust.iml +++ b/.idea/rust.iml @@ -153,10 +153,15 @@ + + + + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 24dcbe8..b841b27 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -14,30 +14,36 @@ - - + + - - + + - - - - - - + + + + + + + + + + + + + + + + - - - - - - - + + + @@ -69,8 +75,6 @@ @@ -153,12 +159,12 @@ - + - + @@ -192,7 +198,7 @@ - + @@ -220,7 +226,7 @@ - + - + @@ -298,11 +304,11 @@ + - @@ -373,20 +379,6 @@ - - - - - - - - - - - - - - @@ -793,10 +785,17 @@ + + + + + + + - - + + @@ -808,10 +807,31 @@ - + + + + - - + + + + + + + + + + + + + + + + + + + + diff --git a/advanced_traits/Cargo.toml b/advanced_traits/Cargo.toml new file mode 100644 index 0000000..dc1eb3b --- /dev/null +++ b/advanced_traits/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "advanced_traits" +version = "0.1.0" +authors = ["Timothy Warren "] +edition = "2018" + +[dependencies] diff --git a/advanced_traits/src/main.rs b/advanced_traits/src/main.rs new file mode 100644 index 0000000..9bfffc0 --- /dev/null +++ b/advanced_traits/src/main.rs @@ -0,0 +1,151 @@ +use std::fmt; +use std::ops::Add; + +#[derive(Debug, PartialEq)] +struct Point { + x: i32, + y: i32, +} + +impl Add for Point { + type Output = Point; + + fn add(self, other: Point) -> Point { + Point { + x: self.x + other.x, + y: self.y + other.y, + } + } +} + +struct Millimeters(u32); +struct Meters(u32); + +/// Implement the Add trait to allow adding +/// The value from a Meters type to a Millimeters type +/// +/// The Add allows the cross-type operator overloading +impl Add for Millimeters { + type Output = Millimeters; + + fn add(self, other: Meters) -> Millimeters { + Millimeters(self.0 + (other.0 * 1000)) + } +} + +// ---------------------------------------------------------- +// Fully qualified method calls +// ---------------------------------------------------------- + +trait Pilot { + fn fly(&self); +} + +trait Wizard { + fn fly(&self); +} + +struct Human; + +impl Pilot for Human { + fn fly(&self) { + println!("This is your captain speaking."); + } +} + +impl Wizard for Human { + fn fly(&self) { + println!("Up!"); + } +} + +impl Human { + fn fly(&self) { + println!("*waving arms furiously*"); + } +} + +trait Animal { + fn baby_name() -> String; +} + +struct Dog; + +impl Dog { + fn baby_name() -> String { + String::from("Spot") + } +} + +impl Animal for Dog { + fn baby_name() -> String { + String::from("puppy") + } +} + +// ---------------------------------------------------------- +// Supertraits +// ---------------------------------------------------------- + +/// This trait requires the supertrait, `fmt::Display` to be +/// implemented to consider itself implemented +trait OutlinePrint: fmt::Display { + fn outline_print(&self) { + let output = self.to_string(); + let len = output.len(); + println!("{}", "*".repeat(len + 4)); + println!("*{}*", " ".repeat(len + 2)); + println!("* {} *", output); + println!("*{}*", " ".repeat(len + 2)); + println!("{}", "*".repeat(len + 4)); + } +} + +impl OutlinePrint for Point {} + +impl fmt::Display for Point { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } +} + +// ------------------------------------------------------------- +// Newtype pattern (Implement external traits on external types) +// ------------------------------------------------------------- + +// Wrap an external type in tuple struct, so it is now local +struct Wrapper(Vec); + +// Implement an extenal trait for the now local type +impl fmt::Display for Wrapper { + fn fmt(&self, f: &mut fm::Formatter) -> fmt::Result { + write!(f, "[{}]", self.0.join(", ")) + } +} + +// ---------------------------------------------------------- + +fn main() { + assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, + Point { x: 3, y: 3 }); + + let person = Human; + + // Explicitly specifying which implementation to use + Pilot::fly(&person); + Wizard::fly(&person); + + // Defaults to the direct implementation + // aka: Human::fly(&person); + person.fly(); + + // Specify the implementation to use for an associated function + // implemented multiple ways with the same name + println!("A baby dog is called a {}", ::baby_name()); + + let display_point = Point { x: 5, y: -3 }; + display_point.outline_print(); + + let w = Wrapper(vec![String::from("hello"), String::from("world")]); + println!("w = {}", w); +}