文章目录
泛型
泛型的目的在于减少重复代码,提高程序的可读性。
使用
在函数定义中使用泛型:
fn identity<T>(x: T) -> T {
x
}
在结构体定义中使用泛型:
struct Point<T, U> {
x: T,
y: U,
}
在枚举类型定义中使用泛型:
enum Result<T, E> {
Ok(T),
Err(E),
}
比较复杂的是在方法定义中使用泛型,如下:
struct Point<T, U> {
x: T,
y: U,
}
impl<T, U> Point<T, U> {
fn add(&self, other: &Point<T, U>) -> Point<T, U> {
Point { x: self.x + other.x, y: self.y + other.y }
}
}
注意上面代码中是impl<T, U>
而不是impl
,这表明任意类型 T
和U
所对应的Point<T, U>
都拥有add
方法。
如果只想为某些特定的类型,比如T=f32
和U=u32
所对应的Point<f32, u32>
,定义add
方法,则如下:
struct Point<T, U> {
x: T,
y: U,
}
impl Point<f32, u32> {
fn add(&self, other: &Point<f32, u32>) -> Point<f32, u32> {
Point { x: self.x + other.x, y: self.y + other.y }
}
}
这时候就是impl
,而不是impl<T, U>
。
还可以将某些类型设置为泛型,将其它的设置为具体类型,如下:
struct Point<T, U> {
x: T,
y: U,
}
impl<T> Point<T, u32> {
fn identity(self) -> Point<T, u32> {
self
}
}
这样,只有Point<T, u32>
类型才拥有identity
方法。
总结来说,我们通过控制impl<>
中的泛型参数,来控制泛型类型具体化后所拥有的方法。比如Point<T, U>
具体化可以得到Point<String, u32>
和Point<String, String>
,因为前者U=u32
,所以它有identity
方法,而后者没有。
我们也可以在为泛型结构体(或泛型枚举类型)实现的方法中使用泛型参数,如下:
struct Point<T, U> {
x: T,
y: U,
}
impl<T, U> Point<T, U> {
fn return_other<V>(&self, other: V) -> V {
other
}
}
这里,我们为Point<T, U>
实现了return_other
方法,该方法的作用是接受任意类型的参数并且将它返回。