Rust—泛型


Rust 的泛型是一种强大的特性,它允许你在编写代码时定义函数、结构体、枚举等,而不预先指定具体的类型。这意味着你可以创建更加通用和可重用的代码,减少了代码重复并提高了代码的灵活性和抽象程度。

类型参数:

在定义泛型时,使用尖括号 <T> 来声明类型参数,其中 T 是一个占位符,代表任何可能的类型。例如,定义一个泛型函数 fn generic_function<T>(value: T) {},这里的 T 就是一个类型参数。

fn max<T: PartialOrd>(x: T, y: T) -> T {
    // 使用 if let 作为简洁的三元表达式,这里利用了 PartialOrd trait 的方法 ge
    if x.ge(&y) {
        x
    } else {
        y
    }
}

#[test]
fn test_func() {
    // 使用泛型函数 max 比较两个整数
    println!("Max of 10 and 20 is {}", max(10, 20)); // 输出 20

    // 使用泛型函数 max 比较两个字符串(在 Rust 中,字符串字面量是 &str 类型)
    println!("Max of 'apple' and 'banana' is {}", max("apple", "banana")); // 输出 'banana'
}
用于结构体
// 定义一个泛型结构体 Pair,它包含两个相同类型的值
struct Pair<T> {
    first: T,
    second: T,
}

impl<T> Pair<T> {
    // 为 Pair 结构体定义一个新方法 new,用于构造 Pair 实例
    fn new(first: T, second: T) -> Self {
        Self { first, second }
    }

    // 定义一个方法 cmp_first_to_second,比较 first 和 second 的大小
    fn cmp_first_to_second(&self) -> bool
    where
        T: PartialOrd, // 添加 trait 约束,要求 T 必须实现了 PartialOrd trait
    {
        self.first.ge(&self.second)
    }
}

#[test]
fn test_struct() {
    // 创建一个 Pair 实例,类型为 i32
    let pair_int = Pair::new(1, 2);
    println!(
        "First greater than second? {}",
        pair_int.cmp_first_to_second()
    ); // 输出 false

    // 创建一个 Pair 实例,类型为 &str
    let pair_str = Pair::new("Tom", "Jerry");
    println!(
        "First greater than second? {}",
        pair_str.cmp_first_to_second()
    ); // 输出 false
}
用于特征
// 定义一个泛型 trait Summary,它有一个方法 summarize
trait Summary<T> {
    fn summarize(&self) -> T;
}

// 为 String 类型实现 Summary trait,返回其长度作为摘要
impl Summary<usize> for String {
    fn summarize(&self) -> usize {
        self.len()
    }
}

// 为自定义类型实现 Summary trait,这里假设我们有某种数据结构需要摘要
struct NewsArticle {
    headline: String,
    content: String,
}

// 实现 Summary trait,返回文章的标题作为摘要
impl Summary<String> for NewsArticle {
    fn summarize(&self) -> String {
        self.headline.clone()
    }
}

#[test]
fn test_trait() {
    let article = NewsArticle {
        headline: String::from("New Study Shows Rust Usage Soars"),
        content: String::from(
            "A recent study found that the use of Rust in system programming has skyrocketed.",
        ),
    };

    println!("Article Summary: {}", article.summarize()); // 输出文章标题
    println!("Length of an empty string: {}", String::new().summarize()); // 输出空字符串长度
}
用于枚举
// 自定义一个泛型枚举,表示数学运算的结果
#[derive(Debug)]
enum MathResult<T> {
    Value(T),
    Error(String),
}

#[test]
fn test_enum() {
    // 使用泛型枚举
    let sum_result: MathResult<i32> = MathResult::Value(5 + 3);
    println!("{:?}", sum_result); // 打印:Value(8)

    let divisor = 2.0;
    let numerator = 6.0;
    let divide_result = if divisor != 0.0 {
        MathResult::Value(numerator / divisor)
    } else {
        MathResult::Error("Division by zero".to_string())
    };

    println!("{:?}", divide_result); // 假设正确处理了除零情况,会打印:Value(结果) 或 Error("Division by zero")

    // 错误示例
    let error_result: MathResult<i32> = MathResult::Error("Invalid input".to_string());
    println!("{:?}", error_result); // 打印:Error("Invalid input")
}
泛型约束 where
struct PairTs<T>
where
    T: Display + Clone,
{
    first: T,
    second: T,
}

impl<T> PairTs<T>
where
    T: Display + Clone,
{
    fn new(first: T, second: T) -> Self {
        PairTs { first, second }
    }

    fn display(&self) {
        println!("First: {}, Second: {}", self.first, self.second);
    }
}

#[test]
fn test_where() {
    let pair = PairTs::new("Rust", "2023");
    pair.display();
}