====== 第十二章 泛型 ======
===== 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(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 {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
}
**不同字段不同类型:**
struct Point {
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 {
x: T,
y: T,
}
impl Point {
fn x(&self) -> &T {
&self.x
}
}
// 只为特定类型实现方法
impl Point {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
**多类型参数的方法:**
struct Point {
x: T,
y: U,
}
impl Point {
fn mixup(self, other: Point) -> Point {
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 ====
enum Option {
Some(T),
None,
}
==== Result ====
enum Result {
Ok(T),
Err(E),
}
==== 自定义泛型枚举 ====
enum Either {
Left(L),
Right(R),
}
fn main() {
let left: Either = Either::Left(42);
let right: Either<(), String> = Either::Right(String::from("hello"));
}
===== 12.5 泛型约束(Trait Bounds)=====
==== 单个约束 ====
fn largest(list: &[T]) -> &T {
// ...
}
==== 多个约束 ====
use std::fmt::Display;
fn notify(item: T) {
println!("{}", item.clone());
}
// 使用where子句(更清晰)
fn notify(item: T)
where
T: Display + Clone,
{
println!("{}", item.clone());
}
==== where子句 ====
fn some_function(t: T, u: U) -> i32
where
T: Display + Clone,
U: Clone + Debug,
{
// ...
0
}
===== 12.6 默认泛型参数 =====
struct Container {
value: T,
extra: U,
}
fn main() {
let c1 = Container:: {
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 {
items: Vec,
}
impl Stack {
fn new() -> Self {
Stack { items: Vec::new() }
}
fn push(&mut self, item: T) {
self.items.push(item);
}
fn pop(&mut self) -> Option {
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 {
first: T,
second: U,
}
impl Pair {
fn new(first: T, second: U) -> Self {
Pair { first, second }
}
fn swap(self) -> Pair {
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(list: &[T], target: &T) -> Option {
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的泛型:
* **泛型函数**:语法定义类型参数
* **泛型结构体**:struct Point
* **泛型枚举**:enum Option
* **泛型约束**:T: PartialOrd + Display
* **where子句**:更清晰的约束语法
* **单态化**:编译期展开,零运行时开销
泛型是Rust实现代码复用的重要机制,结合trait bounds可以提供强大的抽象能力。