高级特征
关联类型
之前的例子中出现过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); }
|