泛型编程
泛型允许你编写适用于多种类型的代码,而不是为每种类型重复编写。泛型与 Trait 结合是 Rust 实现抽象的核心方式。
假设我们要找出列表中的最大值:
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 largest<T: PartialOrd + Copy>(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!("最大的数字是 {}", result);
let char_list = vec!['y', 'm', 'a', 'q']; let result = largest(&char_list); println!("最大的字符是 {}", result);}<T>:声明泛型类型参数T: PartialOrd + Copy:约束 T 必须实现这两个 traitPartialOrd:可以比较大小Copy:可以复制(用于list[0]和&item)
返回引用的版本
Section titled “返回引用的版本”fn largest<T: PartialOrd>(list: &[T]) -> &T { let mut largest = &list[0]; for item in list { if item > largest { largest = item; } } largest}不需要 Copy,因为我们返回的是引用。
struct Point<T> { x: T, y: T,}
fn main() { let integer = Point { x: 5, y: 10 }; let float = Point { x: 1.0, y: 4.0 };}多个泛型参数
Section titled “多个泛型参数”struct Point<T, U> { x: T, y: U,}
fn main() { let both_integer = Point { x: 5, y: 10 }; let both_float = Point { x: 1.0, y: 4.0 }; let integer_and_float = Point { x: 5, y: 4.0 };}标准库中的 Option 和 Result:
enum Option<T> { Some(T), None,}
enum Result<T, E> { Ok(T), Err(E),}方法中的泛型
Section titled “方法中的泛型”为泛型类型实现方法
Section titled “为泛型类型实现方法”struct Point<T> { x: T, y: T,}
impl<T> Point<T> { fn x(&self) -> &T { &self.x }
fn y(&self) -> &T { &self.y }}
fn main() { let p = Point { x: 5, y: 10 }; println!("p.x = {}", p.x());}注意 impl<T> 中的 <T> 声明。
为特定类型实现方法
Section titled “为特定类型实现方法”impl Point<f64> { fn distance_from_origin(&self) -> f64 { (self.x.powi(2) + self.y.powi(2)).sqrt() }}只有 Point<f64> 才有 distance_from_origin 方法。
方法中使用不同的泛型
Section titled “方法中使用不同的泛型”struct Point<T, U> { x: T, y: U,}
impl<T, U> Point<T, U> { fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> { Point { x: self.x, y: other.y, } }}
fn main() { let p1 = Point { x: 5, y: 10.4 }; let p2 = Point { x: "Hello", y: 'c' };
let p3 = p1.mixup(p2); println!("p3.x = {}, p3.y = {}", p3.x, p3.y); // 输出: p3.x = 5, p3.y = c}fn print_debug<T: std::fmt::Debug>(value: T) { println!("{:?}", value);}use std::fmt::{Debug, Display};
fn print_both<T: Debug + Display>(value: T) { println!("Debug: {:?}", value); println!("Display: {}", value);}where 子句
Section titled “where 子句”当约束复杂时,使用 where 更清晰:
use std::fmt::Debug;
fn some_function<T, U>(t: &T, u: &U) -> i32where T: Display + Clone, U: Clone + Debug,{ // ... 0}约束方法实现
Section titled “约束方法实现”use std::fmt::Display;
struct Pair<T> { x: T, y: T,}
// 所有 Pair<T> 都有 new 方法impl<T> Pair<T> { fn new(x: T, y: T) -> Self { Self { x, y } }}
// 只有满足约束的 Pair<T> 才有 cmp_display 方法impl<T: Display + PartialOrd> Pair<T> { fn cmp_display(&self) { if self.x >= self.y { println!("最大的是 x = {}", self.x); } else { println!("最大的是 y = {}", self.y); } }}泛型与生命周期
Section titled “泛型与生命周期”生命周期也是泛型的一种:
fn longest<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a strwhere T: Display,{ println!("公告: {}", ann); if x.len() > y.len() { x } else { y }}结构体中的泛型和生命周期
Section titled “结构体中的泛型和生命周期”struct ImportantExcerpt<'a, T> { part: &'a str, metadata: T,}
impl<'a, T> ImportantExcerpt<'a, T> { fn level(&self) -> i32 { 3 }}单态化与零成本抽象
Section titled “单态化与零成本抽象”Rust 在编译时对泛型代码进行单态化(monomorphization):为每个具体类型生成专门的代码。
let integer = Some(5);let float = Some(5.0);编译后相当于:
enum Option_i32 { Some(i32), None,}
enum Option_f64 { Some(f64), None,}
let integer = Option_i32::Some(5);let float = Option_f64::Some(5.0);这意味着:
- 没有运行时开销
- 泛型代码和手写的具体类型代码性能相同
- 这就是 Rust 的”零成本抽象”
常见泛型模式
Section titled “常见泛型模式”trait Factory { type Output; fn create(&self) -> Self::Output;}
struct IntFactory;
impl Factory for IntFactory { type Output = i32; fn create(&self) -> Self::Output { 42 }}struct RequestBuilder<T> { url: String, body: Option<T>,}
impl<T> RequestBuilder<T> { fn new(url: &str) -> Self { RequestBuilder { url: url.to_string(), body: None, } }
fn body(mut self, body: T) -> Self { self.body = Some(body); self }
fn build(self) -> Request<T> { Request { url: self.url, body: self.body, } }}
struct Request<T> { url: String, body: Option<T>,}类型状态模式
Section titled “类型状态模式”struct Locked;struct Unlocked;
struct Door<State> { _state: std::marker::PhantomData<State>,}
impl Door<Locked> { fn unlock(self) -> Door<Unlocked> { println!("门已解锁"); Door { _state: std::marker::PhantomData } }}
impl Door<Unlocked> { fn lock(self) -> Door<Locked> { println!("门已上锁"); Door { _state: std::marker::PhantomData } }
fn open(&self) { println!("门打开了"); }}
fn main() { let door: Door<Locked> = Door { _state: std::marker::PhantomData }; // door.open(); // 编译错误!锁着的门不能打开 let door = door.unlock(); door.open(); // OK}练习 1:泛型函数
Section titled “练习 1:泛型函数”编写泛型函数 largest,找出切片中的最大值:
fn largest<T: PartialOrd>(list: &[T]) -> &T { // 你的代码}
fn main() { let numbers = vec![34, 50, 25, 100, 65]; println!("最大数字: {}", largest(&numbers));
let chars = vec!['y', 'm', 'a', 'q']; println!("最大字符: {}", largest(&chars));}练习 2:泛型结构体
Section titled “练习 2:泛型结构体”定义泛型结构体 Point<T>,实现方法获取 x 和 y:
struct Point<T> { x: T, y: T,}
impl<T> Point<T> { // 实现 x() 和 y() 方法}
fn main() { let p = Point { x: 5, y: 10 }; println!("x: {}, y: {}", p.x(), p.y());}练习 3:特定类型方法
Section titled “练习 3:特定类型方法”为 Point<f64> 单独实现 distance_from_origin 方法:
impl Point<f64> { fn distance_from_origin(&self) -> f64 { // 计算到原点的距离 }}
fn main() { let p = Point { x: 3.0, y: 4.0 }; println!("距离: {}", p.distance_from_origin()); // 应输出: 5.0}练习 4:泛型约束
Section titled “练习 4:泛型约束”编写函数,接收两个相同类型的值,打印较大的那个:
use std::fmt::Display;
fn print_larger<T>(a: T, b: T)where // 添加适当的约束{ // 你的代码}
fn main() { print_larger(5, 10); print_larger("apple", "banana");}掌握了泛型后,下一章我们将学习迭代器和闭包——Rust 函数式编程的核心。