21·面向对象进阶

泛型

泛型

学习目标

  1. 理解泛型的作用
  2. 掌握结构体、枚举、函数的泛型
  3. 理解单态化
  4. 掌握泛型与 trait 的结合

核心概念

为什么需要泛型

// 没有泛型:为每种类型写一遍
fn max_i32(a: i32, b: i32) -> i32 { if a > b { a } else { b } }
fn max_f64(a: f64, b: f64) -> f64 { if a > b { a } else { b } }

// 有泛型:一个函数搞定
fn max<T: PartialOrd>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

函数泛型

fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in &list[1..] {
        if item > largest {
            largest = item;
        }
    }
    largest
}

fn main() {
    let numbers = vec![34, 50, 25, 100, 65];
    println!("最大数: {}", largest(&numbers));

    let chars = vec!['y', 'm', 'a', 'q'];
    println!("最大字符: {}", largest(&chars));
}

结构体泛型

struct Point<T> {
    x: T,
    y: T,
}

// 不同类型的泛型
struct Point2<T, U> {
    x: T,
    y: U,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

impl Point<f64> {
    fn distance_from_origin(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

fn main() {
    let integer_point = Point { x: 5, y: 10 };
    let float_point = Point { x: 1.0, y: 4.0 };
    println!("距离: {}", float_point.distance_from_origin());
}

枚举泛型

// 标准库的 Option 和 Result 就是泛型枚举
enum Option<T> {
    Some(T),
    None,
}

enum Result<T, E> {
    Ok(T),
    Err(E),
}

// 自定义泛型枚举
enum Either<L, R> {
    Left(L),
    Right(R),
}

impl<L, R> Either<L, R> {
    fn is_left(&self) -> bool {
        matches!(self, Either::Left(_))
    }

    fn unwrap_left(self) -> L {
        match self {
            Either::Left(l) => l,
            Either::Right(_) => panic!("called unwrap_left on Right"),
        }
    }
}

单态化

// 编译器会为每个使用的具体类型生成独立代码
fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
    a + b
}

fn main() {
    let x = add(1, 2);      // 编译器生成 add_i32
    let y = add(1.0, 2.0);  // 编译器生成 add_f64
    // 运行时零开销
}

实践练习

练习 1:泛型栈

struct Stack<T> {
    elements: Vec<T>,
}

impl<T> Stack<T> {
    fn new() -> Self {
        Stack { elements: Vec::new() }
    }

    fn push(&mut self, item: T) {
        self.elements.push(item);
    }

    fn pop(&mut self) -> Option<T> {
        self.elements.pop()
    }

    fn peek(&self) -> Option<&T> {
        self.elements.last()
    }

    fn is_empty(&self) -> bool {
        self.elements.is_empty()
    }
}

fn main() {
    let mut stack = Stack::new();
    stack.push(1);
    stack.push(2);
    println!("{:?}", stack.pop());
}

练习 2:泛型 Pair

struct Pair<T> {
    first: T,
    second: T,
}

impl<T> Pair<T> {
    fn new(first: T, second: T) -> Self {
        Pair { first, second }
    }
}

impl<T: PartialOrd> Pair<T> {
    fn larger(&self) -> &T {
        if self.first >= self.second {
            &self.first
        } else {
            &self.second
        }
    }
}

fn main() {
    let pair = Pair::new(10, 20);
    println!("较大的: {}", pair.larger());
}

常见错误

1. 缺少 trait bound

// ❌ T 可能不支持 >
fn max<T>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

// ✅ 添加约束
fn max<T: PartialOrd>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

2. 泛型参数过多

// ⚠️ 过度泛型化
struct Data<T1, T2, T3, T4, T5> { }
// 考虑用 trait 对象或具体类型

小结

用法语法
函数泛型fn f<T>(x: T)
结构体泛型struct S<T> { }
枚举泛型enum E<T> { }
impl 泛型impl<T> S<T> { }
单态化编译时生成具体类型代码,零运行时开销

练习编辑器

rust
Loading...