2.2 泛型

原文链接: https://rust-unofficial.github.io/too-many-lists/second-generic.html

我们已经接触过 Option 和 Box 里的泛型。但到目前为止,我们还没声明过真正对任意元素泛型的新类型。

其实非常简单。现在就把所有类型都改成泛型:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
pub struct List<T> {
    head: Link<T>,
}

type Link<T> = Option<Box<Node<T>>>;

struct Node<T> {
    elem: T,
    next: Link<T>,
}

只要给所有东西加上尖括号,代码就泛型化了。当然,不能只这么做,否则编译器会大发雷霆。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
> cargo test

error[E0107]: wrong number of type arguments: expected 1, found 0
  --> src/second.rs:14:6
   |
14 | impl List {
   |      ^^^^ expected 1 type argument

error[E0107]: wrong number of type arguments: expected 1, found 0
  --> src/second.rs:36:15
   |
36 | impl Drop for List {
   |               ^^^^ expected 1 type argument

问题很清楚:我们在谈论 List,但它已经不再是原来的那个了。和 Option、Box 一样,现在必须始终说 List<Something>。

那这些 impl 里的 Something 是什么?和 List 一样,我们希望实现适用于所有 T。所以,和 List 一样,让 impl 也带上尖括号:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
impl<T> List<T> {
    pub fn new() -> Self {
        List { head: None }
    }

    pub fn push(&mut self, elem: T) {
        let new_node = Box::new(Node {
            elem: elem,
            next: self.head.take(),
        });

        self.head = Some(new_node);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.head.take().map(|node| {
            self.head = node.next;
            node.elem
        })
    }
}

impl<T> Drop for List<T> {
    fn drop(&mut self) {
        let mut cur_link = self.head.take();
        while let Some(mut boxed_node) = cur_link {
            cur_link = boxed_node.next.take();
        }
    }
}

……就这样!

1
2
3
4
5
6
7
8
9
> cargo test

     Running target/debug/lists-5c71138492ad4b4a

running 2 tests
test first::test::basics ... ok
test second::test::basics ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured

所有代码现在都对任意 T 完全泛型。天哪,Rust 真简单。特别要提一下 new,它甚至都没变:

1
2
3
pub fn new() -> Self {
    List { head: None }
}

沐浴在 Self 的荣光里吧——重构与复制粘贴的守护者。另外,构造 List 实例时我们也不写 List<T>,编译器会根据从期望 List<T> 的函数返回这一事实推断出来。

好,接下来是完全新的行为!

最后修改 August 23, 2026: 更新 (499855b16)