Rust中的泛型:为什么需要以及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust 中的泛型简介



泛型编程(generics)是 Rust 的关键概念之一,它允许编写灵活、可复用且安全的代码。如果您从其他语言(例如 C++ 或 Java)转向 Rust,您可能已经接触过模板或泛型。在 Rust 中,generics 的工作方式类似,但特别强调性能和内存安全。



为什么需要 generics?假设您需要编写一个函数来查找列表中的最大元素。没有 generics,您必须为 i32、f64、String 以及每个自定义类型编写单独的版本。使用 generics,您可以编写一个函数,该函数适用于任何支持比较的类型。



在本文中,我们将探讨 Rust 中的 generics 是什么,如何将它们与函数、结构体和 traits 一起使用,并查看实际示例。



Generics 基础:函数和结构体



泛型函数



了解 generics 最简单的方法是编写一个泛型函数。语法使用尖括号 <T>,其中 T 是类型参数(type parameter)。



fn largest<T>(list: &[T]) -> &T {    let mut largest = &list[0];    for item in list {        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);}


但是,这段代码无法编译!Rust 要求类型 T 实现 PartialOrd trait(用于比较)。我们稍后会讨论约束(trait bounds),现在请记住:generics 允许抽象出具体类型,但编译器必须知道哪些操作是允许的。



泛型结构体



Generics 不仅适用于函数,也适用于自定义数据类型。例如,一个具有坐标的点可以存储整数或浮点数:



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

fn main() { let integer_point = Point { x: 5, y: 10 }; let float_point = Point { x: 1.0, y: 4.0 }; println!("整数点: ({}, {})", integer_point.x, integer_point.y); println!("浮点数点: ({}, {})", float_point.x, float_point.y);}


如果字段具有不同类型,可以使用多个类型参数:



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

fn main() { let pair = Pair { first: 42, second: "答案" }; println!("对: {} 和 {}", pair.first, pair.second);}


带有 Traits 和约束(Trait Bounds)的 Generics



什么是 trait bounds?



Trait bounds 是一种告诉编译器泛型类型必须实现特定 traits 的方式。没有它们,我们无法在泛型值上调用方法。让我们回到 largest 函数并修复它:



use std::cmp::PartialOrd;

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

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


现在该函数只接受支持比较(PartialOrd)的类型。



多重约束



您可以通过 + 指定多个 traits。例如,类型必须既可比较又可克隆:



use std::fmt::Display;

fn print_and_compare

博客

书籍推荐