编程与类型系统09
发表于:2024-07-04 | 分类: 学习

泛型数据结构

解耦关注点

类型参数:类型参数是一个泛型名称的标识符,用作客户端在创建泛型实例时指定的具体类型的占位符。

1
2
3
4
5
6
7
8
9
10
type TransformFunc = (value: number) => number;
type PluckFunc = (value: Widget) => Widget[];

function identity<T>(value: T): T {
return value;
}

function getNum(transform: TransformFunc = identity): number[] {}
function getPluck(pluck: PluckFunc = identity): AssembledWidget[] {}

编译器足够智能,能够推导出 T 应该是什么类型,并不需要显示指定。

可选类型

一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class Optional<T> {
private value: T | undefined;
private assigned: boolean;

constructor(value?: T) {
if (value) {
this.value = value;
this.assigned = true;
} else {
this.value = undefined;
this.assigned = false;
}
}

hasValue(): boolean {
return this.assigned;
}
getValue(): T {
if (!this.assigned) throw new Error("value is undefined");
return <T>this.value;
}
}

这里 value 是可选参数

泛型类型

泛型类型是指参数化一个或多个类型的泛型函数、类、接口等。泛型类型允许我们编写能够使用不同类型的通用代码,从而实现高度的代码重用。

泛型数据结构

数据结构包含 3 个部分:

  • 数据自身: 如下面示例中的树和链表中的 number 和 string 值。数据结构包含数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    class NumTreeNode {
    value: number;
    left: NumTreeNode | undefined;
    right: NumTreeNode | undefined;
    constructor(value: number) {
    this.value = value;
    }
    }
    class StringNode {
    value: string;
    next: StringNode | undefined;
    constructor(value: string) {
    this.value = value;
    }
    }
  • 数据的形状:在二叉树中,以分层的方式布局数据,每个元素最多有两个子元素。在链表中,数据是顺序布局的,一个元素在前一个元素的后面。

  • 一组保留形状的操作:例如,我们的数据结构可能提供了这样的操作,用来添加或移除元素。示例中没有提供这样的操作,但是很容易想到,在一个链表的中间移除一个元素后,我们仍想得到一个链表。

    泛型数据结构处理数据的布局、形状和任何保留形状的操作。无论二叉树中包含的是字符串还是数字,都仍是一个二叉树。通过把数据布局的职责交给独立于任何实际数据内容的泛型数据结构,我们可以让代码变得组件化。

遍历数据结构

迭代器:迭代器是能够用来遍历数据结构的一个对象。它提供了一个标准接口,将数据结构的实际形状对客户端隐藏起来。

上一篇:
编程与类型系统10
下一篇:
编程与类型系统08