什么是泛型
可以使用泛型为像函数签名或结构体这样的项创建定义, 这样它们就可以用于多种不同的具体数据类型
简单来说就是: 在(函数/结构/枚举等)定义时不确定数据类型, 在调用的时候才确定数据类型
为什么要使用泛型: 可以高度重用代码, 而且不会损失性能
在函数定义中使用泛型
泛型可以有很多个, 但先从简单的开始, 先体验一个泛型
rust
// largest_i32 和 lagest_char 实现逻辑都是一样的,
// 唯一不同的就是参数和返回值的数据类型不同
fn largest_i32(list: &[i32]) -> &i32 {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn largest_char(list: &[char]) -> &char {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest_i32(&number_list);
println!("The largest number is {result}");
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest_char(&char_list);
println!("The largest char is {result}");
}
rust
use std::cmp::PartialOrd;
// PartialOrd 是一个让值可以比较大小的 Trait (类似接口)
// T:PartialOrd 表示传入的类型必须是可以被比较大小的
// 两个函数变为一个函数, 仅仅是修改了类型,提高代码重用率
fn largest<T:PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("The largest number is {result}");
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("The largest char is {result}");
}
在结构体定义中使用泛型
rust
struct Rect<T, R> {
width: T,
height: R,
}
fn main() {
// 要不然就全部手动传入
let r1: Rect<f32, u32> = Rect {
width: 2.2,
height: 3
};
println!("r1 width: {}", r1.width);
println!("r1 height: {}", r1.height);
// 要不然就全部自动推导, 不能只手动指定一个
let r2 = Rect {
width: 3.2,
height: 4.5
};
println!("r2 width: {}", r2.width);
println!("r2 height: {}", r2.height);
}
枚举定义中的泛型
rust
pub enum Option<T> {
None,
Some(T),
}
rust
pub enum Result<T, E> {
Ok(T),
Err(E),
}
方法定义中的泛型
rust
struct Rect<T, R> {
width: T,
height: R,
}
impl<T, R> Rect<T, R> {
fn new(width: T, height: R) -> Rect<T, R> {
Rect {
width,
height,
}
}
}
fn main() {
let r1 = Rect::new(2.2, 3);
println!("r1 width: {}", r1.width);
println!("r1 height: {}", r1.height);
}