泛型为什么被称为泛型?

25

冒着变成村庄白痴的风险,有人能解释一下为什么泛型被称为泛型吗?我理解它们的用途和好处,但如果“泛指”泛型的定义是“通用”的,并且泛型集合是类型安全的,那么这不是一个用词不当吗?

例如,ArrayList可以容纳任何对象:

ArrayList myObjects = new ArrayList();
myObjects.Add("one");
myObjects.Add(1);

虽然通用的字符串类型集合只能存储字符串:

var myStrings = new List<string>();
myStrings.Add("one");
myStrings.Add("1");

我不太明白为什么它被称为“泛型”。如果答案是“...这使得设计类和方法可以推迟一个或多个类型的规定,直到客户端代码声明和实例化该类或方法。” 来自这里, 那么我想这是有道理的。也许我之所以会有这种精神上的失误是因为我是在Java引入泛型之后才开始编程的,所以我不记得在它们出现之前的情况了。但还是希望得到任何帮助。
9个回答

23

“Generic” 指的是实现方式。你编写一个通用的列表实现,可以与任何类型一起使用,而不需要为想要使用的每个类型编写特定的实现。


好的,这很有道理。所以实现是通用的,直到你实例化它,此时它就变成了一个“具体”的通用模板? :) - Jonathan S.
或者说,你正在使用通用的特定实例 :P - Anand
1
不要这样使用实例,"instance"已经有了特定的含义。 - Amy B
3
“特定泛型”实际上通常被称为“特化”,但这取决于语言。例如,在.NET中,我们称之为“开放式泛型类型”(仍具有未填充的类型参数)和“封闭式泛型类型��(没有未填充的类型参数)。 - Pavel Minaev

15
我认为像这样的问题的正确答案几乎总是“主要是出于历史原因”。泛型本来可以被称为“方案”、“类”、“类型族”、“种属”、“类型函数”、“静态类型”、“希腊类型”或其他数百万种东西。很久以前,有人决定使用“通用”的这个词,并且它一直沿用至今。
在Java中,“泛型”的概念至少可追溯到20世纪70年代中期。美国国防部正在制定其新编程语言(即将成为ADA)。早期草案(Woodenman,1975年8月)中写道:
“在可扩展语言中需要编译时参数,以允许指定通用过程和数据结构,例如堆栈和队列,而无需为每个元素类型重复定义。”

在该文档中,“generic”一词仅出现一次,我并不清楚它的意图。但是到了1977年7月(见"Tinman"),有一个完整的段落在讨论generics,并且这个术语已经明显具有特定含义:

12D. GENERIC DEFINITIONS

可以定义带有参数的函数、过程和类型,在每次调用时进行实例化翻译。这些参数可以是任何已定义的标识符(包括变量、函数或类型),表达式或语句。这些参数与所有其他参数一样,都应在调用的上下文中进行评估。

到了1978年6月(见"Steelman"),它是一个通行语; 在文档的其他部分还有其他使用“泛型”的用法,明确指代了这个特性。在最终的语言中,“generic”成为了保留字。


我在学术界找到的最早与“generic”相关的使用是在罗宾·米尔纳(Robin Milner)的《编程中的类型多态性理论》(1978年)中(他感到有必要解释他所说的“generic”的含义,因此当时在学术界中并不常见):
引用如下:
因此,这是“map”的通用类型,也就是说,在此声明的范围内,任何“map”的出现都必须分配给该类型的某个替换实例。
“通用类型变量”成为了计算机科学的行话。

泛型的历史非常悠久。谢谢! - Jonathan S.

4
bool Equals(int x, int y)

上述方法只能比较整数,因此我们可以说它是专门用于比较整数的。

bool Equals<T>(T x, T y);

上述方法可以比较任何类型的值,因此我们可以说它不是专门针对任何特定类型的-它是通用的。


1
你会在方法体中放什么? - fastcodejava

1
我不想深入语言(英语,而不是Java)的语义学讨论,并冒着用一句同义反复的回答你的风险; 泛型方法被称为泛型,因为正如你所说的那样,它可以在一般意义上使用,它没有具体的类型,可以通用使用。

这对我来说有些意义...在框架层面上,我们有List<T>,它是泛型的。在实现中变得具体,List<string> - Al Lelopath

1

好的,这只是我的猜测,请带着一颗怀疑的心看待,不过我想它可能是“生成类型”的一种变形。

从概念上讲,当你把一个List转化成List< String >时,它会生成一个新的类型。至少在C++模板和C#泛型中,它是这样工作的。

在Java中,由于参数化被编译器使用类型擦除丢弃,它实际上不会生成一个新的专用类型,所以谁知道呢?

我想你可以说Java实现了一种通用化的生成类型的版本:)


编辑:

这里有另一个观点...

当他们提到“泛型”类型时,他们所说的不是 List< String > 类型。我认为术语实际上是指 List< T > 类型,这是该类型以其泛型形式存在的方式。List< String > 是泛型 List< T > 的一种特化。


0
如果称其为“类型参数”,人们会将其与Type类型的参数混淆。
此外,ArrayList并不是“泛型”。它仅适用于对象类型。如果您请求某些内容,它将给您一个对象引用。这是非常特定的行为。

2
谢谢,我正在研究这个问题,并在谷歌搜索中发现了这篇文章:http://bytes.com/forum/thread244697.html。那时我意识到Jon Skeet无处不在。 - Jonathan S.

0
一个接收对象的类并不是泛型,它非常明确地接收一个本身就是泛型类型的类型。另一方面,泛型类可以与任何特定类型一起使用。

0

因为你正在创建“通用”代码,它将能够以相同的方式操作任何类型(在你指定的约束范围内)...

一个你熟悉的很好的例子是“加法”运算符几乎在任何语言中都可以使用... 它可以对整数、浮点数、双精度数、十进制数、二进制数、十六进制数进行“加法”运算,无论它们是有符号的还是无符号的,有多少位等等...


-1

我不是“本地”的英语说话者,所以可能会有错误,但“泛型”的重点是定义泛型类型,不是吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接