高级特征
关联类型
之前的例子中出现过Item这个占位符
- 关联类型在trait中指定占位符类型
(1) 关联类型是一个将类型占位符与trait相关联的方式
(2) trait的实现者会针对特定的实现在这个类型的位置指定相应的具体类型,可以通过这样使用多种类型的trait 
1 2 3 4
   | pub trait Iterator {     type Item;     fn next(&mut self) -> Option<Self::Item>;   }
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   | pub trait Iterator1<T> {     fn next(&mut self) -> Option<T>;   }
  struct A {     value: i32,   } impl Iterator1<i32> for A {     fn next(&mut self) -> Option<i32> {         println!("in i32");         if self.value > 3 {             self.value += 1;             Some(self.value)           } else {               None             }       }   } impl Iterator1<String> for A {     fn next(&mut self) -> Option<String> {         println!("in string");         if self.value > 3 {             self.value += 1;             Some("hello".to_string())           } else {               None             }       }   } fn main() {     let a = 4;               <A as Iterator1<i32>>::next(&mut a);     <A as Iterator1<String>>::next(&mut a);   }
  | 
 
这种写法比较烦锁,使用自定义迭代器中的关联类型较为好些:
😘自定义迭代器
默认泛型类型参数和运算符重载
- 使用泛型类型参数时,可以为泛型指定一个默认的具体操作
 
- 运算符重载指在特定情况下自定义运算符行为的操作
 
- 可以进行重载的运算符或者自定义运算符只能是Rust已经有的运算符,如我们可以为std::ops
中的运算符和相应的trait实现运算符相关trait重载 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | 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); impl Add<Meters> for Millimeters {     type Output = Millimeters;     fn add(self,other: Meters) -> Millimeters {           Millimeters(self.0+other.0*1000)       }   }
  fn main() {     assert_eq!(Point{x:1,y:1}+ Point {x:2,y:3},Point{x:3,y:4});     let mi = Millimeters(1);     let m = Meters(1);     let r = mi + m;     println!("r = {:?}",r);   }
 
 
 
 
 
   | 
 
完全限定语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
   | trait A {     fn print(&self);   } trait B {     fn print(&self);   }
  struct MyType;
  impl A for MyType {     fn print(&self) {         println!("A trait for MyType");       }   } impl B for MyType {     fn print(&self) {         println!("B trait for MyType");       }   } impl MyType {     fn print(&self) {         println!("MyType");       }   }
  fn main() {     let m = MyType;     m.print();
      A::print(&m);     B::print(&m);     MyType::print(&m);   }
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | 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")       }   }
  fn main() {     println!("baby_name: {}",Dog::baby_name());                println!("baby_name: {}",<Dog as Animal>::baby_name()); 
    }
  | 
 
父Trait
某些时刻需要某个trait使用另外一些trait的功能,需要能够依赖的trait也被实现,这种
trait就是父trait
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | use std::fmt; trait OutPrint: fmt::Display {       fn out_print(&self) {           let output = self.to_string();           println!("output {}",output);         }   }
  struct Point {     x: i32,     y: i32,   }
  impl OutPrint for Point {}
  impl fmt::Display for Point {     fn fmt(&self,f :&mut fmt::Formatter) -> fmt::Result {         write!(f,"({},{})",self.x,self.y);       }   } fn main() {
    }
   | 
 
newtype模式
newtype模式用来在外部类型上实现外部Trait
- 孤儿规则(orphan rule):只要trait或者类型对于当前crate是本地的话就可以在此类型上
实现该Trait 
- 不是本地地一个绕开这个限制的方法是使用newtype模式(newtype pattern)
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13
   | use std::fmt; struct Wrapper(Vec<String>);
  impl fmt::Display for Wrapper {     fn fmt(&self,f: &mut fmt::Formatter) -> fmt::Result {         write!(f,"{},{}",self.0.join(","));       }   }
  fn main() {     let w = Wrapper(vec![String::from("hello"),String::from("world")]);     println!("w = {}",w);    }
   |