Skip to content

21.1 数据结构中的泛型

有时候,我们需要针对多种类型进行统一的抽象,这就是泛型。泛型可以将“类型”作为参数,在函数或者数据结构中使用。

再以我们熟悉的 Option 类型举例。它就是一个泛型 enum 类型,其参数声明在尖括号<>中。


rust
enum Option<T> {
    Some(T),
    None,
}

这里的<T>实际上是声明了一个“类型”参数。在这个 Option 内部,Some(T)是一个 tuple struct,包含一个元素类型为 T。这个泛型参数类型 T,可以在使用时指定具体类型。


rust
let x: Option<i32> = Some(42);
let y: Option<f64> = None;

在上述第一行代码中,泛型参数 T 被具体化成了 i32,x 的类型,在这里是Option<i32>;在第二行代码中,泛型参数 T 被具体化成了 f64,y 的类型,在这里是Option<f64>

泛型参数可以有多个也可以有默认值。比如:


rust
struct S<T=i32> {
    data: T
}

fn main() {
    let v1 = S { data: 0};
    let v2 = S::<bool> { data: false};
    println!("{} {}", v1.data, v2.data);
}

对于上例中的泛型参数 T,我们可以在使用的时候不指定类型参数。如果不指定的话,参数默认为 i32,也可以在使用的时候指定为其他类型。

使用不同类型参数将泛型类型具体化后,获得的是完全不同的具体类型。如Option<i32>Option<i64>是完全不同的类型,不可通用,也不可相互转换。当编译器生成代码的时候,它会为每一个不同的泛型参数生成不同的代码。

各种自定义复合类型都可以携带任意的泛型参数。Rust 规定,所有的泛型参数必须是真的被使用过的。下面的代码就会报错:


rust
struct Num<T> {
    data: i32
}

这个结构体声明了一个泛型参数,但是却并没有使用它。编译器会对这个问题报错,说有泛型参数从来没有使用过。按下面这样写就没有问题了:


rust
struct Num<T> {
    data: Option<T>
}

Released under the MIT License