六、泛型
Published on
泛型是用于编写功能确定,类型待定的代码模板的机制,可以有效减少代码冗余。类似于C++中的模板。
在函数中使用
// 定义一个使用泛型的函数
fn foo<T>(arg: T) {
...
}
// 编译器自动识别T为i32
foo(1);
// 编译器自动识别T为&str
foo("string");
// 手动设置T为i32
foo::<i32>(1);
在结构体中使用
// 定义一个使用泛型的结构体
struct Point<T> {
x: T,
y: T,
}
// 自动识别T为i32
let integer = Point { x: 5, y: 10 };
// 自动识别T为f64
let float = Point { x: 1.0, y: 4.0 };
// 错误,x与y必须具有相同的类型
let wont_work = Point { x: 5, y: 4.0 };
// 手动设置T为u8
let uint8 = Point::<u8> { x: 1, y: 2 };
在枚举中使用
std库中的Option与Result是非常常用的使用了泛型的枚举结构。
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
在实现中使用
// 如果实现泛型方法,需要在impl后使用泛型
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
// 只为Point<f32>类型实现方法
impl Point<f32> {
fn x(&self) -> &f32 {
&self.x
}
}
在特性中使用
// 声明一个泛型特性
trait DoubleDrop<T> {
fn double_drop(self, _: T);
}
// 实现上述特性
impl<T, U> DoubleDrop<T> for U {
fn double_drop(self, _: T) {}
}
特性范围(trait bound)
在使用泛型时,有时需要要求参数实现指定的特性。
// 要求参数T实现Display特性
fn printer<T: Display>(t: T) {
println!("{}", t);
}
// 要求参数实现多个特性
fn compare_prints<T: Debug + Display>(t: &T) {
println!("Debug: `{:?}`", t);
println!("Display: `{}`", t);
}
// 使用where子句使代码更加易读
impl <A: TraitB + TraitC, D: TraitE + TraitF> MyTrait<A, D> for YourType {}
impl <A, D> MyTrait<A, D> for YourType where
A: TraitB + TraitC,
D: TraitE + TraitF {}