rust:第十二章泛型
目录
第十二章 泛型
12.1 什么是泛型
泛型(Generics)是具体类型或其他属性的抽象替代。使用泛型可以编写适用于多种类型的代码,减少重复。
泛型的作用:
- 代码复用:一次编写,多种类型适用
- 类型安全:编译时检查类型
- 零成本抽象:编译期单态化,无运行时开销
12.2 泛型函数
提取最大值
不使用泛型(重复代码):
fn largest_i32(list: &[i32]) -> i32 { let mut largest = list[0]; for &item in list.iter() { if item > largest { largest = item; } } largest } fn largest_char(list: &[char]) -> char { let mut largest = list[0]; for &item in list.iter() { if item > largest { largest = item; } } largest }
使用泛型:
fn largest<T: PartialOrd>(list: &[T]) -> &T { let mut largest = &list[0]; for item in list.iter() { if item > largest { largest = item; } } largest } fn main() { let numbers = vec![34, 50, 25, 100, 65]; let result = largest(&numbers); println!("最大数字是{}", result); let chars = vec!['y', 'm', 'a', 'q']; let result = largest(&chars); println!("最大字符是{}", result); }
12.3 泛型结构体
定义泛型结构体
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 }; }
不同字段不同类型:
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 }; }
泛型结构体的方法
struct Point<T> { x: T, y: T, } impl<T> Point<T> { fn x(&self) -> &T { &self.x } } // 只为特定类型实现方法 impl Point<f32> { fn distance_from_origin(&self) -> f32 { (self.x.powi(2) + self.y.powi(2)).sqrt() } }
多类型参数的方法:
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 }
12.4 泛型枚举
Option<T>
enum Option<T> { Some(T), None, }
Result<T, E>
enum Result<T, E> { Ok(T), Err(E), }
自定义泛型枚举
enum Either<L, R> { Left(L), Right(R), } fn main() { let left: Either<i32, ()> = Either::Left(42); let right: Either<(), String> = Either::Right(String::from("hello")); }
12.5 泛型约束(Trait Bounds)
单个约束
fn largest<T: PartialOrd>(list: &[T]) -> &T { // ... }
多个约束
use std::fmt::Display; fn notify<T: Display + Clone>(item: T) { println!("{}", item.clone()); } // 使用where子句(更清晰) fn notify<T>(item: T) where T: Display + Clone, { println!("{}", item.clone()); }
where子句
fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug, { // ... 0 }
12.6 默认泛型参数
struct Container<T, U = i32> { value: T, extra: U, } fn main() { let c1 = Container::<String, f64> { value: String::from("hello"), extra: 3.14, }; let c2 = Container { value: String::from("world"), extra: 42, // 使用默认类型i32 }; }
12.7 泛型与性能
单态化(Monomorphization):
Rust在编译时将泛型代码转换为具体类型的代码,没有运行时开销。
// 源代码 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);
练习题
练习题12.1:泛型栈
struct Stack<T> { items: Vec<T>, } impl<T> Stack<T> { fn new() -> Self { Stack { items: Vec::new() } } fn push(&mut self, item: T) { self.items.push(item); } fn pop(&mut self) -> Option<T> { self.items.pop() } fn peek(&self) -> Option<&T> { self.items.last() } fn is_empty(&self) -> bool { self.items.is_empty() } fn size(&self) -> usize { self.items.len() } } fn main() { let mut stack = Stack::new(); stack.push(1); stack.push(2); stack.push(3); println!("栈顶:{:?}", stack.peek()); println!("弹出:{:?}", stack.pop()); println!("大小:{}", stack.size()); }
练习题12.2:泛型Pair
struct Pair<T, U> { first: T, second: U, } impl<T, U> Pair<T, U> { fn new(first: T, second: U) -> Self { Pair { first, second } } fn swap(self) -> Pair<U, T> { Pair { first: self.second, second: self.first, } } } fn main() { let pair = Pair::new(1, "hello"); println!("first: {}, second: {}", pair.first, pair.second); let swapped = pair.swap(); println!("交换后:first: {}, second: {}", swapped.first, swapped.second); }
练习题12.3:泛型查找
fn find<T: PartialEq>(list: &[T], target: &T) -> Option<usize> { for (i, item) in list.iter().enumerate() { if item == target { return Some(i); } } None } fn main() { let numbers = vec![1, 2, 3, 4, 5]; match find(&numbers, &3) { Some(index) => println!("找到在索引{}", index), None => println!("未找到"), } let words = vec!["hello", "world", "rust"]; match find(&words, &"rust") { Some(index) => println!("找到在索引{}", index), None => println!("未找到"), } }
本章小结
本章学习了Rust的泛型:
- 泛型函数:<T>语法定义类型参数
- 泛型结构体:struct Point<T, U>
- 泛型枚举:enum Option<T>
- 泛型约束:T: PartialOrd + Display
- where子句:更清晰的约束语法
- 单态化:编译期展开,零运行时开销
泛型是Rust实现代码复用的重要机制,结合trait bounds可以提供强大的抽象能力。
rust/第十二章泛型.txt · 最后更改: 由 127.0.0.1
