泛型

48 阅读3分钟

在软件工程领域,构建具有良好定义、一致性API且可重用的组件是极为关键的一部分。这些组件不仅能够处理当前的数据,还能适应未来的数据需求,从而为构建大型软件系统提供最大的灵活性。在C#Java等编程语言中,泛型是创建可重用组件的主要工具之一。泛型允许开发者创建能够在多种类型而非单一类型上工作的组件。这意味着用户可以使用这些组件,并根据自己的需求应用它们自己的数据类型。

简单来说,泛型使得代码更加灵活和通用。例如,在C#中,你可以定义一个泛型列表(List<T>),其中T是一个占位符,代表将来可以被替换为任何类型的对象实际,数据类型都可以。使用这个这样泛型,列表无论是,整数、字符串还是自定义而无需为每种类型编写单独的列表实现。

通过使用泛型,开发者可以编写更加简洁、易于维护且高度可重用的代码。这不仅提高了代码的质量,还大大减少了开发和维护的工作量。因此,在设计和实现软件组件时,考虑使用泛型是一个非常重要的策略。

泛型版本Hello World

让我们从最简单的例子——泛型版本的“身份函数”(identity function)开始。身份函数是一个接受任何类型的参数并返回相同类型参数的函数,类似于命令行中的 echo 命令。

如果不使用泛型,就必须给函数特定的类型:

function identity(arg: number): number {
  return arg
}

或者使用any类型:

function identity(arg: any): any {
  return arg
}

虽然使用 any 确实很通用,因为它会让函数接受任何类型的参数 arg,但函数返回时丢失了关于该类型的信息。如果我们传递了一个数字,我们唯一知道的信息就是任何类型的值都可能被返回。
相反,我们需要一种方法来捕获参数的类型,以便也能用它来表示返回的内容。在这里,我们将使用一种类型的变量,这是一种专门用于处理类型而不是值的特殊变量。

function identity<Type>(arg: Type): Type {
  return arg;
}

我们说这个版本的恒等函数是泛型的,因为它可以作用于一系列类型。与使用any不同,它也像第一个使用数字作为参数和返回类型的恒等函数一样精确(即,它不会丢失任何信息)。一旦我们编写了泛型恒等函数,就可以通过以下两种方式之一来调用它。第一种方式是将所有参数,包括类型参数,传递给函数:

在函数indentity中添加类型变量Type。这个Type允许我们捕获用户提供的类型(例如:number),以便我们稍后可以使用这些信息。在这里,我们同样使用Type作为返回值类型。

这个版本的indentity函数就是泛型函数。因为它对任何类型的参数都有用。与any不同的是,我们清楚传递进去了什么类型,以及返回了什么类型。

let output = identity("myString");

使用泛型类型变量