样做的目的是为了避免过度
设计,
因为很有可能第二次变化永远也不会出现,而你却花费了大量的时间精力制造了一个永远也用不
到的“完美设计”。这很像一个谚语,“fool
me
once,shame
on
you.
fool
me
twice,
shame
on
me.”,
翻译过来的意思是“愚弄我一次,是你坏;愚弄我两次,是我蠢”。
美好的事情总是很难长久,我们很快需要对一个
char类型的数组进行排序,我们当然可以
仿照
byte类型数组的作法,继续采用复制粘贴大法,然后修改一下方法的签名。但是很遗憾,
我们不想让它愚弄我们两次,因为谁也不想证明自己很蠢,所以现在是时候思考一个更佳的解决
方案了。
我们仔细地对比这两个方法,会发现这两个方法的实现完全一样,除了方法的签名不同以外,
没有任何的区别。如果你曾经开发过
Web站点程序,会知道对于一些浏览量非常大的站点,为
了避免服务器负担过重,通常会采用静态页面生成的方式,因为使用
Url重写仍要要耗费大量的
服务器资源,但是生成为
html静态网页后,服务器仅仅是返回
客户端请求的文件,能够极大的
减轻服务器负担。
在
Web上实现过静态页面生成时,有一种
常用的方法,就是模板生成法,它的具体作法是:
每次生成静态页面时,先加载模板,模板中含有一些用特殊字符标记的占位符,然后我们从数据
库读取数据,使用读出的数据将模板中的占位符替换掉,最后将模板按照一定的命名规则在服务
器上保存成静态的
html文件。
我们发现这里的情况是类似的,我来对它进行一个类比:我们将上面的方法体视为一个模板,
4
4444/
1
11114
4444
将它的方法签名视为一个占位符,因为它是一个占位符,所以它可以代表任何的类型,这和静态
页面生成时模板的占位符可以用来代表来自数据库中的任何数据道理是一样的。接下来就是定义
占位符了,我们再来审视一下这两个方法的签名:
public
void
BubbleSort(int[]
array)
public
void
BubbleSort(byte[]
array)
public
void
BubbleSort(char[]
array)
会发现定义占位符的最好方式就是将
int[]、byte[]、char[]用占位符替代掉,我们管这个占位
符用
T[]来表示,其中
T可以代表任何类型,这样就屏蔽了三个方法签名的差异:
public
void
BubbleSort(T[]
array)
{
int
length
=array.Length;
for
(int
i
=0;
i<=
length
-2;
i++)
{
for(int
j
=
length
-1;
j>=
1;
j--)
{
//对两个元素进行交换
if
(array[j]
-1])
{
Ttemp
=array[j];
array[j]
=array[j
-1];
array[j
-1]
=temp;
}
}
}
}
现在看起来清爽多了,但是我们又发现了一个问题:当我们定义一个类,而这个类需要引用
它本身以外的其他类型时,我们可以定义有参数的构造函数,然后将它需要的参数从构造函数传
进来。但是在上面,我们的参数
T本身就是一个类型(类似于
int、byte、char,而不是类型的实
例,比如
1和'a')。很显然我们无法在构造函数中传递这个
T类型的数组,因为参数都是出现在
类型实例的位置,而
T是类型本身,它的位置不对。比如下面是通常的构造函数:
public
SortHelper(类型类型实例名称);
5
5555/
1
11114
4444
而我们期望的构造函数函数是:
public
SortHelper(类型);
此时就需要使用一种特殊的语法来传递这个
T占位符,不如我们定义这样一种语法来传递
吧:
public
class
SortHelper
{
public
void
BubbleSort(T[]
array){
//方法实现体
}
}
我们在类名称的后面加了一个尖括号,使用这个尖括号来传递我们的占位符,也就是类型参
数。接下来,我们来看看如何来使用它,当我们
需要为一个
int类型的数组排序时:
SortHelper
sorter
=newSortHelper();
int[]
array
={
8,
1,
4,
7,
3};
sorter.BubbleSort(array);
当我们需要为一个
byte类型的数组排序时:
SortHelpersorter
=
newSortHelper();
byte[]
array
={8,
1,
4,
7,
3
};
sorter.BubbleSort(array);
相信你已经发觉,其实上面所做的一切实现了一个泛型类。这是泛型的一个最典型的应用,
可以看到,通过使用泛型,我们极大地减少了重复代码,使我们的程序更加清爽,泛型类就类似
于一个模板,可以在需要时为这个模板传入任何我们需要的类型。
我们现在更专业一些,为这一节的占位符起一个正式的名称,在.Net中,它叫做类型参数
(T
TTTTy
yyyyp
ppppe
eeeeP
PPPPa
aaaar
rrrra
aaaam
mmmme
eeeet
tttte
eeeer
rrrr),下面一小节,我们将学习类型参数约束。